Generate random avatar based on e-mail when disable Gravatar
This commit is contained in:
		
							parent
							
								
									56a8d573b0
								
							
						
					
					
						commit
						4b43ffc96c
					
				
					 4 changed files with 59 additions and 4 deletions
				
			
		|  | @ -14,6 +14,7 @@ github.com/go-xorm/core = | ||||||
| github.com/go-xorm/xorm =  | github.com/go-xorm/xorm =  | ||||||
| github.com/gogits/chardet = commit:2404f77725 | github.com/gogits/chardet = commit:2404f77725 | ||||||
| github.com/gogits/go-gogs-client = commit:92e76d616a | github.com/gogits/go-gogs-client = commit:92e76d616a | ||||||
|  | github.com/issue9/identicon =  | ||||||
| github.com/lib/pq = commit:0dad96c0b9 | github.com/lib/pq = commit:0dad96c0b9 | ||||||
| github.com/macaron-contrib/binding = commit:de6ed78668 | github.com/macaron-contrib/binding = commit:de6ed78668 | ||||||
| github.com/macaron-contrib/cache = commit:cd824f6f2d | github.com/macaron-contrib/cache = commit:cd824f6f2d | ||||||
|  |  | ||||||
|  | @ -13,7 +13,9 @@ import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"image" | 	"image" | ||||||
| 	"image/jpeg" | 	"image/jpeg" | ||||||
|  | 	_ "image/jpeg" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  | @ -116,11 +118,39 @@ func (u *User) HomeLink() string { | ||||||
| 
 | 
 | ||||||
| // AvatarLink returns user gravatar link.
 | // AvatarLink returns user gravatar link.
 | ||||||
| func (u *User) AvatarLink() string { | func (u *User) AvatarLink() string { | ||||||
|  | 	defaultImgUrl := setting.AppSubUrl + "/img/avatar_default.jpg" | ||||||
|  | 	imgPath := path.Join(setting.AvatarUploadPath, com.ToStr(u.Id)) | ||||||
| 	switch { | 	switch { | ||||||
| 	case u.UseCustomAvatar: | 	case u.UseCustomAvatar: | ||||||
|  | 		if !com.IsExist(imgPath) { | ||||||
|  | 			return defaultImgUrl | ||||||
|  | 		} | ||||||
| 		return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id) | 		return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id) | ||||||
| 	case setting.DisableGravatar, setting.OfflineMode: | 	case setting.DisableGravatar, setting.OfflineMode: | ||||||
| 		return setting.AppSubUrl + "/img/avatar_default.jpg" | 		if !com.IsExist(imgPath) { | ||||||
|  | 			img, err := avatar.RandomImage([]byte(u.Email)) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error(3, "RandomImage: %v", err) | ||||||
|  | 				return defaultImgUrl | ||||||
|  | 			} | ||||||
|  | 			if err = os.MkdirAll(path.Dir(imgPath), os.ModePerm); err != nil { | ||||||
|  | 				log.Error(3, "Create: %v", err) | ||||||
|  | 				return defaultImgUrl | ||||||
|  | 			} | ||||||
|  | 			fw, err := os.Create(imgPath) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error(3, "Create: %v", err) | ||||||
|  | 				return defaultImgUrl | ||||||
|  | 			} | ||||||
|  | 			defer fw.Close() | ||||||
|  | 
 | ||||||
|  | 			if err = jpeg.Encode(fw, img, nil); err != nil { | ||||||
|  | 				log.Error(3, "Encode: %v", err) | ||||||
|  | 				return defaultImgUrl | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id) | ||||||
| 	case setting.Service.EnableCacheAvatar: | 	case setting.Service.EnableCacheAvatar: | ||||||
| 		return setting.AppSubUrl + "/avatar/" + u.Avatar | 		return setting.AppSubUrl + "/avatar/" + u.Avatar | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -19,9 +19,11 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"image" | 	"image" | ||||||
|  | 	"image/color/palette" | ||||||
| 	"image/jpeg" | 	"image/jpeg" | ||||||
| 	"image/png" | 	"image/png" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"math/rand" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"os" | 	"os" | ||||||
|  | @ -30,6 +32,7 @@ import ( | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/issue9/identicon" | ||||||
| 	"github.com/nfnt/resize" | 	"github.com/nfnt/resize" | ||||||
| 
 | 
 | ||||||
| 	"github.com/gogits/gogs/modules/log" | 	"github.com/gogits/gogs/modules/log" | ||||||
|  | @ -59,6 +62,27 @@ func HashEmail(email string) string { | ||||||
| 	return hex.EncodeToString(h.Sum(nil)) | 	return hex.EncodeToString(h.Sum(nil)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const _RANDOM_AVATAR_SIZE = 200 | ||||||
|  | 
 | ||||||
|  | // RandomImage generates and returns a random avatar image.
 | ||||||
|  | func RandomImage(data []byte) (image.Image, error) { | ||||||
|  | 	randExtent := len(palette.WebSafe) - 32 | ||||||
|  | 	rand.Seed(time.Now().UnixNano()) | ||||||
|  | 	colorIndex := rand.Intn(randExtent) | ||||||
|  | 	backColorIndex := colorIndex - 1 | ||||||
|  | 	if backColorIndex < 0 { | ||||||
|  | 		backColorIndex = randExtent - 1 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Size, background, forecolor
 | ||||||
|  | 	imgMaker, err := identicon.New(_RANDOM_AVATAR_SIZE, | ||||||
|  | 		palette.WebSafe[backColorIndex], palette.WebSafe[colorIndex:colorIndex+32]...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return imgMaker.Make(data), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Avatar represents the avatar object.
 | // Avatar represents the avatar object.
 | ||||||
| type Avatar struct { | type Avatar struct { | ||||||
| 	Hash           string | 	Hash           string | ||||||
|  |  | ||||||
|  | @ -14,19 +14,19 @@ | ||||||
| 			      <div class="ui selection dropdown"> | 			      <div class="ui selection dropdown"> | ||||||
| 			        <input type="hidden" id="uid" name="uid" value="{{.ContextUser.Id}}" required> | 			        <input type="hidden" id="uid" name="uid" value="{{.ContextUser.Id}}" required> | ||||||
| 			        <span class="text"> | 			        <span class="text"> | ||||||
| 			        	<img class="ui mini avatar image" src="{{.ContextUser.AvatarLink}}"> | 			        	<img class="ui mini image" src="{{.ContextUser.AvatarLink}}"> | ||||||
|             		{{.ContextUser.Name}} |             		{{.ContextUser.Name}} | ||||||
|             	</span> |             	</span> | ||||||
| 			        <i class="dropdown icon"></i> | 			        <i class="dropdown icon"></i> | ||||||
| 			        <div class="menu"> | 			        <div class="menu"> | ||||||
| 			        	<div class="item" data-value="{{.SignedUser.Id}}"> | 			        	<div class="item" data-value="{{.SignedUser.Id}}"> | ||||||
| 				        	<img class="ui mini avatar image" src="{{.SignedUser.AvatarLink}}"> | 				        	<img class="ui mini image" src="{{.SignedUser.AvatarLink}}"> | ||||||
| 	            		{{.SignedUser.Name}} | 	            		{{.SignedUser.Name}} | ||||||
| 			        	</div> | 			        	</div> | ||||||
| 			        	{{range .Orgs}} | 			        	{{range .Orgs}} | ||||||
| 			        	{{if .IsOwnedBy $.SignedUser.Id}} | 			        	{{if .IsOwnedBy $.SignedUser.Id}} | ||||||
| 			        	<div class="item" data-value="{{.Id}}"> | 			        	<div class="item" data-value="{{.Id}}"> | ||||||
| 				        	<img class="ui mini avatar image" src="{{.AvatarLink}}"> | 				        	<img class="ui mini image" src="{{.AvatarLink}}"> | ||||||
| 	            		{{.Name}} | 	            		{{.Name}} | ||||||
| 			        	</div> | 			        	</div> | ||||||
| 			        	{{end}} | 			        	{{end}} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue