-
Notifications
You must be signed in to change notification settings - Fork 1
/
gofilego.go
217 lines (193 loc) · 4.95 KB
/
gofilego.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package gofilego
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"strconv"
"strings"
"time"
)
// VERSION represents the version of the library
const VERSION = "v0.2"
// Connection represents a basic Gofile upload struct
type Connection struct {
// Upload server name
Server string
// Map of files, represented by [filename]io.Reader
FilesUploaded map[string]io.Reader
// Upload email
Email string
// Upload description
Description string
// Upload Password
Password string
// Upload tags provided as string array
Tags []string
// Expiration date timestamp
Expire int64
}
type bestServerResponse struct {
Status string
Data map[string]string
}
// UploadResponse is a struct representing the json response of the Gofile server
type UploadResponse struct {
Status string
Data map[string]interface{}
}
// GetNewServer refreshes best server via contacting gofile api
func (conn *Connection) GetNewServer() error {
const getServerUrl = "https://apiv2.gofile.io/getServer"
request, err := http.Get(getServerUrl)
if err != nil {
return err
}
defer request.Body.Close()
response, err := ioutil.ReadAll(request.Body)
if err != nil {
return err
}
// Parse response
bestServer := new(bestServerResponse)
err = json.Unmarshal(response, bestServer)
if err != nil {
return err
}
if bestServer.Status == "ok" {
conn.Server = bestServer.Data["server"]
return nil
}
return errors.New("Couldn't obtain new server")
}
func (conn *Connection) noRepeat(name string) string {
if _, exists := conn.FilesUploaded[name]; exists {
name = "(Copy)- " + name
conn.noRepeat(name)
}
return name
}
// Setters
// AddFile adds a file to the current connection struct
func (conn *Connection) AddFile(name string, file io.Reader) {
key := conn.noRepeat(name)
conn.FilesUploaded[key] = file
}
// SetEmail sets upload email
func (conn *Connection) SetEmail(email string) {
conn.Email = email
}
// SetDescription sets upload description
func (conn *Connection) SetDescription(desc string) {
conn.Description = desc
}
// SetPassword sets upload password
func (conn *Connection) SetPassword(pass string) {
conn.Password = pass
}
// SetTags receives tags as variadic arguments.
func (conn *Connection) SetTags(tags ...string) {
conn.Tags = tags
}
// SetExpire sets expiration timestamp as a time.Time object
func (conn *Connection) SetExpire(timeStamp time.Time) {
conn.Expire = timeStamp.Unix()
}
// NewConnection creates a new default connection. Returns a basic connection struct.
func NewConnection() (*Connection, error) {
conn := new(Connection)
err := conn.build()
if err != nil {
return conn, err
}
return conn, nil
}
func (conn *Connection) build() error {
err := conn.GetNewServer()
conn.FilesUploaded = make(map[string]io.Reader)
if err != nil {
return err
}
return nil
}
// Construct acts as a constructor. Requires a Connection struct.
func (conn *Connection) Construct(providedStruct *Connection) {
*conn = *providedStruct
conn.build()
}
// Upload files to gofile, using the Connection struct parameters
func (conn *Connection) Upload() (*UploadResponse, error) {
url := fmt.Sprintf("https://%s.gofile.io/upload", conn.Server)
buffer := new(bytes.Buffer)
multiWriter := multipart.NewWriter(buffer)
for _, reader := range conn.FilesUploaded {
var fileWriter io.Writer
var err error
if x, ok := reader.(io.Closer); ok {
defer x.Close()
}
if x, ok := reader.(*os.File); ok {
if fileWriter, err = multiWriter.CreateFormFile("filesUploaded", x.Name()); err != nil {
return nil, err
}
} else {
if fileWriter, err = multiWriter.CreateFormField("filesUploaded"); err != nil {
return nil, err
}
}
if _, err := io.Copy(fileWriter, reader); err != nil {
return nil, err
}
}
conn.generateFormFields(multiWriter)
multiWriter.Close()
request, err := http.NewRequest("POST", url, buffer)
if err != nil {
return nil, err
}
request.Header.Set("Content-Type", multiWriter.FormDataContentType())
client := &http.Client{}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
responseJson := new(UploadResponse)
content, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
json.Unmarshal(content, responseJson)
return responseJson, nil
}
func (conn *Connection) generateFormFields(multiWriter *multipart.Writer) {
if conn.Email != "" {
multiWriter.WriteField("email", conn.Email)
}
if conn.Description != "" {
multiWriter.WriteField("description", conn.Description)
}
if conn.Password != "" {
multiWriter.WriteField("password", conn.Password)
}
if conn.Tags != nil {
var tags string
for _, tag := range conn.Tags {
// TODO sanitize inputs
if strings.Contains(tag, ",") {
continue
}
tags = tags + "," + tag
}
tags = strings.TrimPrefix(tags, ",")
multiWriter.WriteField("tags", tags)
}
if conn.Expire != 0 {
multiWriter.WriteField("expire", strconv.Itoa(int(conn.Expire)))
}
}