Skip to content

Commit 6b8c743

Browse files
committed
Merge pull request #56 from minotar/develop
Merge in Minotar 1.0
2 parents 4c60d8c + 3d19c29 commit 6b8c743

18 files changed

+112
-279
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
language: go
2+
23
go:
3-
- 1.0
44
- 1.1
55
- tip

README.md

+2-9
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,7 @@ Need Steve? Use "char" as the username:
4646
`<img src="https://minotar.net/skin/char">`
4747

4848
## How to install?
49-
1. Setup your GOPATH properly.
50-
2. go get github.com/Axxim/Minotar/minotard
51-
3. cp -Rf $GOPATH/src/github.com/Axxim/Minotar/minotard/static $GOPATH/bin
52-
4. cd $GOPATH/bin; ./minotard
53-
54-
and it'll be listening on port 9999 on all interfaces.
55-
56-
You'll then need to either edit the source to listen on the port you want, or use something like nginx as a reverse proxy.
49+
- Coming Soon -
5750

5851
## Understanding Headers
5952
We use a couple of headers to help in understanding how something is served, here they are:
@@ -74,4 +67,4 @@ x-timing:
7467
- example: 48+0+4=52
7568

7669
## Thanks
77-
Big thanks to [lukegb](https://github.com/lukegb) for porting this script from PHP to Go!
70+
Big thanks to [lukegb](https://github.com/lukegb) for porting the old version of this script from PHP to Go.

doc.go

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// minotar project doc.go
2+
3+
/*
4+
minotar document
5+
*/
6+
package main

examples/fetchandtest.go

-42
This file was deleted.

minotard/minogosrv.go main.go

+73-60
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package main
22

3-
////// THIS CODE IS RELEASED INTO THE PUBLIC DOMAIN. SEE "UNLICENSE" FOR MORE INFORMATION. http://unlicense.org //////
4-
53
import (
64
"fmt"
7-
"github.com/Axxim/Minotar"
85
"github.com/gorilla/mux"
6+
"github.com/minotar/minecraft"
97
"image"
108
"io"
119
"log"
@@ -18,21 +16,22 @@ import (
1816
)
1917

2018
const (
21-
DEFAULT_SIZE = uint(180)
22-
MAX_SIZE = uint(300)
23-
MIN_SIZE = uint(8)
19+
DefaultSize = uint(180)
20+
MaxSize = uint(300)
21+
MinSize = uint(8)
2422

25-
STATIC_LOCATION = "static"
23+
StaticLocation = "www"
24+
SkinCache
2625

27-
LISTEN_ON = ":9999"
26+
ListenOn = ":9999"
2827

29-
MINUTES uint = 60
30-
HOURS = 60 * MINUTES
31-
DAYS = 24 * HOURS
32-
TIMEOUT_ACTUAL_SKIN = 2 * DAYS
33-
TIMEOUT_FAILED_FETCH = 15 * MINUTES
28+
Minutes uint = 60
29+
Hours = 60 * Minutes
30+
Days = 24 * Hours
31+
TimeoutActualSkin = 2 * Days
32+
TimeoutFailedFetch = 15 * Minutes
3433

35-
SERVICE_VERSION = "0.3"
34+
MinotarVersion = "1.0"
3635
)
3736

3837
func serveStatic(w http.ResponseWriter, r *http.Request, inpath string) error {
@@ -43,7 +42,7 @@ func serveStatic(w http.ResponseWriter, r *http.Request, inpath string) error {
4342
inpath = "/" + inpath
4443
r.URL.Path = inpath
4544
}
46-
path := STATIC_LOCATION + inpath
45+
path := StaticLocation + inpath
4746

4847
f, err := os.Open(path)
4948
if err != nil {
@@ -102,11 +101,11 @@ func rationalizeSize(inp string) uint {
102101
out64, err := strconv.ParseUint(inp, 10, 0)
103102
out := uint(out64)
104103
if err != nil {
105-
return DEFAULT_SIZE
106-
} else if out > MAX_SIZE {
107-
return MAX_SIZE
108-
} else if out < MIN_SIZE {
109-
return MIN_SIZE
104+
return DefaultSize
105+
} else if out > MaxSize {
106+
return MaxSize
107+
} else if out < MinSize {
108+
return MinSize
110109
}
111110
return out
112111
}
@@ -124,7 +123,7 @@ func timeBetween(timeA time.Time, timeB time.Time) int64 {
124123
return timeB.Sub(timeA).Nanoseconds() / 1000000
125124
}
126125

127-
func fetchImageProcessThen(callback func(minotar.Skin) (image.Image, error)) func(w http.ResponseWriter, r *http.Request) {
126+
func fetchImageProcessThen(callback func(minecraft.Skin) (image.Image, error)) func(w http.ResponseWriter, r *http.Request) {
128127
return func(w http.ResponseWriter, r *http.Request) {
129128
timeReqStart := time.Now()
130129

@@ -134,22 +133,25 @@ func fetchImageProcessThen(callback func(minotar.Skin) (image.Image, error)) fun
134133
size := rationalizeSize(vars["size"])
135134
ok := true
136135

137-
var skin minotar.Skin
136+
var skin minecraft.Skin
138137
var err error
139-
if username == "char" {
140-
if skin, err = minotar.FetchSkinForSteve(); err != nil {
141-
serverErrorPage(w, r)
142-
return
143-
}
144-
} else {
145-
if skin, err = minotar.FetchSkinForUser(username); err != nil {
146-
ok = false
147-
if skin, err = minotar.FetchSkinForSteve(); err != nil {
148-
serverErrorPage(w, r)
149-
return
150-
}
138+
139+
// Fetch image using username
140+
skin, err = minecraft.GetSkin(minecraft.User{Name: username})
141+
if err != nil {
142+
// Problem with the returned image, probably means we have an incorrect username
143+
// Hit the accounts api
144+
user, err := minecraft.GetUser(username)
145+
146+
if err != nil {
147+
// There's no account for this person, serve char
148+
skin, _ = minecraft.GetSkin(minecraft.User{Name: "char"})
149+
} else {
150+
// Get valid skin
151+
skin, _ = minecraft.GetSkin(user)
151152
}
152153
}
154+
153155
timeFetch := time.Now()
154156

155157
img, err := callback(skin)
@@ -159,41 +161,52 @@ func fetchImageProcessThen(callback func(minotar.Skin) (image.Image, error)) fun
159161
}
160162
timeProcess := time.Now()
161163

162-
imgResized := minotar.Resize(size, size, img)
164+
imgResized := Resize(size, size, img)
163165
timeResize := time.Now()
164166

165167
w.Header().Add("Content-Type", "image/png")
166168
w.Header().Add("X-Requested", "processed")
167169
var timeout uint
168170
if ok {
169171
w.Header().Add("X-Result", "ok")
170-
timeout = TIMEOUT_ACTUAL_SKIN
172+
timeout = TimeoutActualSkin
171173
} else {
172174
w.Header().Add("X-Result", "failed")
173-
timeout = TIMEOUT_FAILED_FETCH
175+
timeout = TimeoutFailedFetch
174176
}
175-
w.Header().Add("X-Timing", fmt.Sprintf("%d+%d+%d=%d", timeBetween(timeReqStart, timeFetch), timeBetween(timeFetch, timeProcess), timeBetween(timeProcess, timeResize), timeBetween(timeReqStart, timeResize)))
177+
w.Header().Add("X-Timing", fmt.Sprintf("%d+%d+%d=%dms", timeBetween(timeReqStart, timeFetch), timeBetween(timeFetch, timeProcess), timeBetween(timeProcess, timeResize), timeBetween(timeReqStart, timeResize)))
176178
addCacheTimeoutHeader(w, timeout)
177-
minotar.WritePNG(w, imgResized)
179+
WritePNG(w, imgResized)
178180
}
179181
}
180182
func skinPage(w http.ResponseWriter, r *http.Request) {
181183
vars := mux.Vars(r)
182184

183185
username := vars["username"]
184186

185-
userSkinURL := minotar.URLForUser(username)
186-
resp, err := http.Get(userSkinURL)
187-
if err != nil {
188-
notFoundPage(w, r)
189-
return
190-
}
187+
user, _ := minecraft.GetUser(username)
188+
skin, _ := minecraft.GetSkin(user)
189+
191190
w.Header().Add("Content-Type", "image/png")
192191
w.Header().Add("X-Requested", "skin")
193192
w.Header().Add("X-Result", "ok")
194-
addCacheTimeoutHeader(w, TIMEOUT_ACTUAL_SKIN)
195-
defer resp.Body.Close()
196-
io.Copy(w, resp.Body)
193+
194+
WritePNG(w, skin.Image)
195+
196+
/*
197+
userSkinURL := minotar.URLForUser(username)
198+
resp, err := http.Get(userSkinURL)
199+
if err != nil {
200+
notFoundPage(w, r)
201+
return
202+
}
203+
w.Header().Add("Content-Type", "image/png")
204+
w.Header().Add("X-Requested", "skin")
205+
w.Header().Add("X-Result", "ok")
206+
addCacheTimeoutHeader(w, TIMEOUT_ACTUAL_SKIN)
207+
defer resp.Body.Close()
208+
io.Copy(w, resp.Body)
209+
*/
197210
}
198211
func downloadPage(w http.ResponseWriter, r *http.Request) {
199212
headers := w.Header()
@@ -202,33 +215,33 @@ func downloadPage(w http.ResponseWriter, r *http.Request) {
202215
}
203216

204217
func main() {
205-
avatarPage := fetchImageProcessThen(func(skin minotar.Skin) (image.Image, error) {
206-
return skin.Head()
218+
avatarPage := fetchImageProcessThen(func(skin minecraft.Skin) (image.Image, error) {
219+
return GetHead(skin)
207220
})
208-
helmPage := fetchImageProcessThen(func(skin minotar.Skin) (image.Image, error) {
209-
return skin.Helm()
221+
helmPage := fetchImageProcessThen(func(skin minecraft.Skin) (image.Image, error) {
222+
return GetHelm(skin)
210223
})
211224

212225
r := mux.NewRouter()
213226
r.NotFoundHandler = NotFoundHandler{}
214227

215-
r.HandleFunc("/avatar/{username:"+minotar.VALID_USERNAME_REGEX+"}{extension:(.png)?}", avatarPage)
216-
r.HandleFunc("/avatar/{username:"+minotar.VALID_USERNAME_REGEX+"}/{size:[0-9]+}{extension:(.png)?}", avatarPage)
228+
r.HandleFunc("/avatar/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", avatarPage)
229+
r.HandleFunc("/avatar/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", avatarPage)
217230

218-
r.HandleFunc("/helm/{username:"+minotar.VALID_USERNAME_REGEX+"}{extension:(.png)?}", helmPage)
219-
r.HandleFunc("/helm/{username:"+minotar.VALID_USERNAME_REGEX+"}/{size:[0-9]+}{extension:(.png)?}", helmPage)
231+
r.HandleFunc("/helm/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", helmPage)
232+
r.HandleFunc("/helm/{username:"+minecraft.ValidUsernameRegex+"}/{size:[0-9]+}{extension:(.png)?}", helmPage)
220233

221-
r.HandleFunc("/download/{username:"+minotar.VALID_USERNAME_REGEX+"}{extension:(.png)?}", downloadPage)
234+
r.HandleFunc("/download/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", downloadPage)
222235

223-
r.HandleFunc("/skin/{username:"+minotar.VALID_USERNAME_REGEX+"}{extension:(.png)?}", skinPage)
236+
r.HandleFunc("/skin/{username:"+minecraft.ValidUsernameRegex+"}{extension:(.png)?}", skinPage)
224237

225238
r.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
226-
fmt.Fprintf(w, "%s", SERVICE_VERSION)
239+
fmt.Fprintf(w, "%s", MinotarVersion)
227240
})
228241

229242
r.HandleFunc("/", indexPage)
230243

231244
http.Handle("/", r)
232245
http.HandleFunc("/assets/", serveAssetPage)
233-
log.Fatalln(http.ListenAndServe(LISTEN_ON, nil))
246+
log.Fatalln(http.ListenAndServe(ListenOn, nil))
234247
}

0 commit comments

Comments
 (0)