pylon-api 1.1.0 → 1.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 +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/pylon/client.rb +83 -3
- data/lib/pylon/version.rb +1 -1
- data/lib/pylon.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f54f7ed75e823866e06256d1a598bb3158e686131156932b7aad3d9a90da9c7
|
4
|
+
data.tar.gz: fe68e2c1be8128acadd4179b2baa2751fd9223fdbe1a5c66cb35d2d41c13fae0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6282c28251d01ed1f7c196fbb421c3e895d37681da8e71e5941ed74db3ff88aff39e8e9c8604fe899d555e61aec5bc7b8824fcdf30e6e789c3b74086d25ae7ee
|
7
|
+
data.tar.gz: bf00a26818a96154c91a2a1f281d219372f0fd97b8b0075ddbb70fcebaa675c28b31e55a10bf218303fcc4e2b0ad15229a30950e2f2a5e41cd174995940c0a2a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [1.1.1] - 2025-04-18
|
4
|
+
|
5
|
+
### Fixed
|
6
|
+
- Fixed URL-based file attachments by ensuring they use proper multipart form encoding
|
7
|
+
|
8
|
+
## [1.1.0] - 2025-04-17
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- Support for URL-based file attachments
|
12
|
+
- Enhanced attachment handling for various file types
|
13
|
+
- Added MIME type detection for file uploads
|
14
|
+
|
3
15
|
## [1.0.0] - 2024-03-21
|
4
16
|
|
5
17
|
### Changed
|
data/lib/pylon/client.rb
CHANGED
@@ -7,7 +7,22 @@ module Pylon
|
|
7
7
|
# client = Pylon::Client.new(api_key: 'your_api_key')
|
8
8
|
# issues = client.list_issues(start_time: '2024-03-01T00:00:00Z', end_time: '2024-03-31T23:59:59Z')
|
9
9
|
# issues.each { |issue| puts issue.title }
|
10
|
+
# rubocop:disable Metrics/ClassLength
|
10
11
|
class Client
|
12
|
+
# Common MIME types for file uploads
|
13
|
+
MIME_TYPES = {
|
14
|
+
".jpg" => "image/jpeg",
|
15
|
+
".jpeg" => "image/jpeg",
|
16
|
+
".png" => "image/png",
|
17
|
+
".gif" => "image/gif",
|
18
|
+
".pdf" => "application/pdf",
|
19
|
+
".doc" => "application/msword",
|
20
|
+
".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
21
|
+
".xls" => "application/vnd.ms-excel",
|
22
|
+
".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
23
|
+
".csv" => "text/csv",
|
24
|
+
".txt" => "text/plain"
|
25
|
+
}
|
11
26
|
# Base URL for the Pylon API
|
12
27
|
BASE_URL = "https://api.usepylon.com"
|
13
28
|
|
@@ -45,10 +60,36 @@ module Pylon
|
|
45
60
|
|
46
61
|
# Create a new attachment
|
47
62
|
#
|
48
|
-
# @param file [String] The file
|
63
|
+
# @param file [File, String, nil] The file to upload (File object or file content)
|
64
|
+
# @param description [String, nil] A text description of the file
|
65
|
+
# @param file_url [String, nil] A URL to fetch the file from if file is not provided
|
49
66
|
# @return [Models::Attachment] Created attachment object
|
50
|
-
|
51
|
-
|
67
|
+
# @raise [ArgumentError] If neither file nor file_url is provided
|
68
|
+
def create_attachment(file = nil, description: nil, file_url: nil)
|
69
|
+
if file.nil? && file_url.nil?
|
70
|
+
raise ArgumentError, "Either file or file_url must be provided"
|
71
|
+
end
|
72
|
+
|
73
|
+
params = {}
|
74
|
+
params[:description] = description if description
|
75
|
+
params[:file_url] = file_url if file_url
|
76
|
+
|
77
|
+
if file
|
78
|
+
if file.is_a?(::File) || (file.respond_to?(:path) && file.respond_to?(:read))
|
79
|
+
# For File objects or IO-like objects
|
80
|
+
params[:file] = Faraday::UploadIO.new(file, mime_type_for_file(file), File.basename(file.path))
|
81
|
+
else
|
82
|
+
# For raw content as string, create a temp file
|
83
|
+
temp_file = Tempfile.new(["upload", ".bin"])
|
84
|
+
temp_file.binmode
|
85
|
+
temp_file.write(file)
|
86
|
+
temp_file.rewind
|
87
|
+
params[:file] = Faraday::UploadIO.new(temp_file, "application/octet-stream")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Always use multipart for attachments, whether file or file_url
|
92
|
+
post_multipart("/attachments", params, model_class: Models::Attachment)
|
52
93
|
end
|
53
94
|
|
54
95
|
# Get details for a specific attachment
|
@@ -324,6 +365,17 @@ module Pylon
|
|
324
365
|
end
|
325
366
|
end
|
326
367
|
|
368
|
+
# Determine MIME type for file
|
369
|
+
#
|
370
|
+
# @param file [File] The file to determine MIME type for
|
371
|
+
# @return [String] The MIME type
|
372
|
+
def mime_type_for_file(file)
|
373
|
+
return "application/octet-stream" unless file.respond_to?(:path)
|
374
|
+
|
375
|
+
ext = File.extname(file.path).downcase
|
376
|
+
MIME_TYPES[ext] || "application/octet-stream"
|
377
|
+
end
|
378
|
+
|
327
379
|
# Handle API response and raise appropriate errors
|
328
380
|
#
|
329
381
|
# @param response [Faraday::Response] The API response
|
@@ -427,6 +479,34 @@ module Pylon
|
|
427
479
|
handle_response(connection.post(path, body.to_json), model_class, collection)
|
428
480
|
end
|
429
481
|
|
482
|
+
# Make a multipart POST request for file uploads
|
483
|
+
#
|
484
|
+
# @param path [String] The API endpoint path
|
485
|
+
# @param params [Hash] Request parameters including file uploads
|
486
|
+
# @param model_class [Class] The model class to use for wrapping the response
|
487
|
+
# @param collection [Boolean] Whether the response is a collection of items
|
488
|
+
# @return [Models::Base, Models::Collection, Array] Model, Collection, or response data array
|
489
|
+
def post_multipart(path, params = {}, model_class: nil, collection: false)
|
490
|
+
# Create a connection without the default JSON content type for multipart uploads
|
491
|
+
multipart_conn = Faraday.new(@base_url) do |f|
|
492
|
+
f.request :multipart
|
493
|
+
# Only force multipart for file_url uploads, omit url_encoded middleware
|
494
|
+
f.response :json, content_type: /\bjson$/
|
495
|
+
f.response :logger if @debug
|
496
|
+
f.adapter Faraday.default_adapter
|
497
|
+
f.headers["Authorization"] = "Bearer #{api_key}"
|
498
|
+
f.headers["Accept"] = "application/json"
|
499
|
+
end
|
500
|
+
|
501
|
+
# If we have a file_url but no actual file, create a dummy file part to force multipart encoding
|
502
|
+
if params[:file_url] && !params[:file]
|
503
|
+
# Create an empty file part to force multipart encoding
|
504
|
+
params[:_dummy] = Faraday::FilePart.new(StringIO.new(""), "application/octet-stream", "dummy")
|
505
|
+
end
|
506
|
+
|
507
|
+
handle_response(multipart_conn.post(path, params), model_class, collection)
|
508
|
+
end
|
509
|
+
|
430
510
|
# Make a PATCH request
|
431
511
|
#
|
432
512
|
# @param path [String] The API endpoint path
|
data/lib/pylon/version.rb
CHANGED
data/lib/pylon.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pylon-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Odom
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|