@@ -8,11 +8,13 @@ import (
8
8
"net/http"
9
9
"os"
10
10
"path/filepath"
11
+ "strings"
11
12
)
12
13
13
14
///////////////////////////////////////////////////////////////////////////////
14
15
// TYPES
15
16
17
+ // General attachment metadata
16
18
type AttachmentMeta struct {
17
19
Id string `json:"id,omitempty"`
18
20
Filename string `json:"filename,omitempty"`
@@ -21,9 +23,17 @@ type AttachmentMeta struct {
21
23
Data []byte `json:"data"`
22
24
}
23
25
26
+ // OpenAI image metadata
27
+ type ImageMeta struct {
28
+ Url string `json:"url,omitempty"`
29
+ Data []byte `json:"b64_json,omitempty"`
30
+ Prompt string `json:"revised_prompt,omitempty"`
31
+ }
32
+
24
33
// Attachment for messages
25
34
type Attachment struct {
26
- meta AttachmentMeta
35
+ meta * AttachmentMeta
36
+ image * ImageMeta
27
37
}
28
38
29
39
const (
@@ -38,6 +48,11 @@ func NewAttachment() *Attachment {
38
48
return new (Attachment )
39
49
}
40
50
51
+ // NewAttachment with OpenAI image
52
+ func NewAttachmentWithImage (image * ImageMeta ) * Attachment {
53
+ return & Attachment {image : image }
54
+ }
55
+
41
56
// ReadAttachment returns an attachment from a reader object.
42
57
// It is the responsibility of the caller to close the reader.
43
58
func ReadAttachment (r io.Reader ) (* Attachment , error ) {
@@ -50,7 +65,7 @@ func ReadAttachment(r io.Reader) (*Attachment, error) {
50
65
filename = f .Name ()
51
66
}
52
67
return & Attachment {
53
- meta : AttachmentMeta {
68
+ meta : & AttachmentMeta {
54
69
Filename : filename ,
55
70
Data : data ,
56
71
},
@@ -73,19 +88,25 @@ func (a *Attachment) MarshalJSON() ([]byte, error) {
73
88
Filename string `json:"filename,omitempty"`
74
89
Type string `json:"type"`
75
90
Bytes uint64 `json:"bytes"`
76
- Caption string `json:"transcript ,omitempty"`
91
+ Caption string `json:"caption ,omitempty"`
77
92
}
78
- j .Id = a .meta .Id
79
- j .Filename = a .meta .Filename
93
+
80
94
j .Type = a .Type ()
81
- j .Bytes = uint64 (len (a .meta .Data ))
82
- j .Caption = a .meta .Caption
95
+ j .Caption = a .Caption ()
96
+ if a .meta != nil {
97
+ j .Id = a .meta .Id
98
+ j .Filename = a .meta .Filename
99
+ j .Bytes = uint64 (len (a .meta .Data ))
100
+ } else if a .image != nil {
101
+ j .Bytes = uint64 (len (a .image .Data ))
102
+ }
103
+
83
104
return json .Marshal (j )
84
105
}
85
106
86
107
// Stringify an attachment
87
108
func (a * Attachment ) String () string {
88
- data , err := json .MarshalIndent (a . meta , "" , " " )
109
+ data , err := json .MarshalIndent (a , "" , " " )
89
110
if err != nil {
90
111
return err .Error ()
91
112
}
@@ -95,68 +116,98 @@ func (a *Attachment) String() string {
95
116
////////////////////////////////////////////////////////////////////////////////
96
117
// PUBLIC METHODS
97
118
119
+ // Write out attachment
120
+ func (a * Attachment ) Write (w io.Writer ) (int , error ) {
121
+ if a .meta != nil {
122
+ return w .Write (a .meta .Data )
123
+ }
124
+ if a .image != nil {
125
+ return w .Write (a .image .Data )
126
+ }
127
+ return 0 , io .EOF
128
+ }
129
+
98
130
// Return the filename of an attachment
99
131
func (a * Attachment ) Filename () string {
100
- return a .meta .Filename
132
+ if a .meta != nil {
133
+ return a .meta .Filename
134
+ } else {
135
+ return ""
136
+ }
101
137
}
102
138
103
139
// Return the raw attachment data
104
140
func (a * Attachment ) Data () []byte {
105
- return a .meta .Data
141
+ if a .meta != nil {
142
+ return a .meta .Data
143
+ }
144
+ if a .image != nil {
145
+ return a .image .Data
146
+ }
147
+ return nil
106
148
}
107
149
108
150
// Return the caption for the attachment
109
151
func (a * Attachment ) Caption () string {
110
- return a .meta .Caption
152
+ if a .meta != nil {
153
+ return strings .TrimSpace (a .meta .Caption )
154
+ }
155
+ if a .image != nil {
156
+ return strings .TrimSpace (a .image .Prompt )
157
+ }
158
+ return ""
111
159
}
112
160
113
161
// Return the mime media type for the attachment, based
114
162
// on the data and/or filename extension. Returns an empty string if
115
163
// there is no data or filename
116
164
func (a * Attachment ) Type () string {
117
165
// If there's no data or filename, return empty
118
- if len (a .meta . Data ) == 0 && a .meta . Filename == "" {
166
+ if len (a .Data ()) == 0 && a .Filename () == "" {
119
167
return ""
120
168
}
121
169
122
170
// Mimetype based on content
123
171
mimetype := defaultMimetype
124
- if len (a .meta . Data ) > 0 {
125
- mimetype = http .DetectContentType (a .meta . Data )
172
+ if len (a .Data () ) > 0 {
173
+ mimetype = http .DetectContentType (a .Data () )
126
174
if mimetype != defaultMimetype {
127
175
return mimetype
128
176
}
129
177
}
130
178
131
179
// Mimetype based on filename
132
- if a .meta . Filename != "" {
180
+ if a .Filename () != "" {
133
181
// Detect mimetype from extension
134
- mimetype = mime .TypeByExtension (filepath .Ext (a .meta . Filename ))
182
+ mimetype = mime .TypeByExtension (filepath .Ext (a .Filename () ))
135
183
}
136
184
137
185
// Return the default mimetype
138
186
return mimetype
139
187
}
140
188
141
189
func (a * Attachment ) Url () string {
142
- return "data:" + a .Type () + ";base64," + base64 .StdEncoding .EncodeToString (a .meta . Data )
190
+ return "data:" + a .Type () + ";base64," + base64 .StdEncoding .EncodeToString (a .Data () )
143
191
}
144
192
145
193
// Streaming includes the ability to append data
146
194
func (a * Attachment ) Append (other * Attachment ) {
147
- if other .meta .Id != "" {
148
- a .meta .Id = other .meta .Id
149
- }
150
- if other .meta .Filename != "" {
151
- a .meta .Filename = other .meta .Filename
152
- }
153
- if other .meta .ExpiresAt != 0 {
154
- a .meta .ExpiresAt = other .meta .ExpiresAt
155
- }
156
- if other .meta .Caption != "" {
157
- a .meta .Caption += other .meta .Caption
158
- }
159
- if len (other .meta .Data ) > 0 {
160
- a .meta .Data = append (a .meta .Data , other .meta .Data ... )
195
+ if a .meta != nil {
196
+ if other .meta .Id != "" {
197
+ a .meta .Id = other .meta .Id
198
+ }
199
+ if other .meta .Filename != "" {
200
+ a .meta .Filename = other .meta .Filename
201
+ }
202
+ if other .meta .ExpiresAt != 0 {
203
+ a .meta .ExpiresAt = other .meta .ExpiresAt
204
+ }
205
+ if other .meta .Caption != "" {
206
+ a .meta .Caption += other .meta .Caption
207
+ }
208
+ if len (other .meta .Data ) > 0 {
209
+ a .meta .Data = append (a .meta .Data , other .meta .Data ... )
210
+ }
161
211
}
212
+ // TODO: Append for image
162
213
}
0 commit comments