2014-12-01 07:32:35 +00:00
|
|
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
|
|
|
|
|
|
|
class Avatar < ApplicationModel
|
2015-04-27 13:42:53 +00:00
|
|
|
belongs_to :object_lookup, class_name: 'ObjectLookup'
|
2014-12-01 07:32:35 +00:00
|
|
|
|
|
|
|
=begin
|
|
|
|
|
2015-02-15 08:36:18 +00:00
|
|
|
add an avatar based on auto detection (email address)
|
2014-12-01 07:32:35 +00:00
|
|
|
|
|
|
|
Avatar.auto_detection(
|
2015-05-04 18:58:28 +00:00
|
|
|
:object => 'User',
|
|
|
|
:o_id => user.id,
|
|
|
|
:url => 'somebody@example.com',
|
|
|
|
:source => 'web',
|
|
|
|
:updated_by_id => 1,
|
|
|
|
:created_by_id => 1,
|
2014-12-01 07:32:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.auto_detection(data)
|
2014-12-01 12:06:47 +00:00
|
|
|
|
|
|
|
# return if we run import mode
|
|
|
|
return if Setting.get('import_mode')
|
2014-12-01 07:32:35 +00:00
|
|
|
return if !data[:url]
|
|
|
|
return if data[:url].empty?
|
|
|
|
|
|
|
|
# dry gravatar lookup
|
|
|
|
hash = Digest::MD5.hexdigest(data[:url])
|
|
|
|
url = "http://www.gravatar.com/avatar/#{hash}.jpg?s=160&d=404"
|
2015-05-04 18:58:28 +00:00
|
|
|
logger.info "Avatar.auto_detection found #{data[:url]}: #{url}"
|
2014-12-01 07:32:35 +00:00
|
|
|
|
|
|
|
Avatar.add(
|
2015-04-27 13:42:53 +00:00
|
|
|
object: data[:object],
|
|
|
|
o_id: data[:o_id],
|
|
|
|
url: url,
|
|
|
|
source: 'gravatar.com',
|
|
|
|
deletable: false,
|
|
|
|
updated_by_id: 1,
|
|
|
|
created_by_id: 1,
|
2014-12-01 07:32:35 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
add a avatar
|
|
|
|
|
|
|
|
Avatar.add(
|
2015-05-04 18:58:28 +00:00
|
|
|
:object => 'User',
|
|
|
|
:o_id => user.id,
|
|
|
|
:default => true,
|
|
|
|
:full => {
|
2014-12-01 07:32:35 +00:00
|
|
|
:content => '...',
|
|
|
|
:mime_type => 'image/png',
|
|
|
|
},
|
|
|
|
:resize => {
|
|
|
|
:content => '...',
|
|
|
|
:mime_type => 'image/png',
|
|
|
|
},
|
2015-05-04 18:58:28 +00:00
|
|
|
:source => 'web',
|
|
|
|
:updated_by_id => 1,
|
|
|
|
:created_by_id => 1,
|
2014-12-01 07:32:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.add(data)
|
|
|
|
|
|
|
|
# lookups
|
|
|
|
if data[:object]
|
|
|
|
object_id = ObjectLookup.by_name( data[:object] )
|
|
|
|
end
|
|
|
|
|
2015-02-15 08:36:18 +00:00
|
|
|
# add initial avatar
|
2014-12-01 07:32:35 +00:00
|
|
|
add_init_avatar(object_id, data[:o_id])
|
|
|
|
|
|
|
|
record = {
|
2015-04-27 13:42:53 +00:00
|
|
|
o_id: data[:o_id],
|
|
|
|
object_lookup_id: object_id,
|
|
|
|
default: true,
|
|
|
|
deletable: data[:deletable],
|
|
|
|
initial: false,
|
|
|
|
source: data[:source],
|
|
|
|
source_url: data[:url],
|
|
|
|
updated_by_id: data[:updated_by_id],
|
|
|
|
created_by_id: data[:created_by_id],
|
2014-12-01 07:32:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# check if avatar with url already exists
|
|
|
|
avatar_already_exists = nil
|
|
|
|
if data[:source] && !data[:source].empty?
|
2015-05-07 10:15:40 +00:00
|
|
|
avatar_already_exists = Avatar.find_by(
|
2015-04-27 13:42:53 +00:00
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: data[:o_id],
|
|
|
|
source: data[:source],
|
2015-05-07 10:15:40 +00:00
|
|
|
)
|
2014-12-01 07:32:35 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# fetch image
|
|
|
|
if data[:url] && data[:url] =~ /^http/
|
|
|
|
|
|
|
|
# check if source ist already updated within last 2 minutes
|
|
|
|
if avatar_already_exists
|
|
|
|
if avatar_already_exists.source_url == data[:url]
|
|
|
|
if avatar_already_exists.updated_at > 2.minutes.ago
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# twitter workaround to get bigger avatar images
|
|
|
|
# see also https://dev.twitter.com/overview/general/user-profile-images-and-banners
|
2015-05-01 12:12:37 +00:00
|
|
|
if data[:url] =~ %r{//pbs.twimg.com/}i
|
2014-12-01 07:32:35 +00:00
|
|
|
data[:url].sub!(/normal\.png$/, 'bigger.png')
|
|
|
|
end
|
|
|
|
|
|
|
|
# fetch image
|
2015-03-22 22:13:39 +00:00
|
|
|
response = UserAgent.get(
|
|
|
|
data[:url],
|
2015-03-23 00:31:30 +00:00
|
|
|
{},
|
2015-03-22 22:13:39 +00:00
|
|
|
{
|
2015-04-27 13:42:53 +00:00
|
|
|
open_timeout: 4,
|
|
|
|
read_timeout: 6,
|
2015-03-22 22:13:39 +00:00
|
|
|
},
|
|
|
|
)
|
2014-12-01 07:32:35 +00:00
|
|
|
if !response.success?
|
2015-05-04 18:58:28 +00:00
|
|
|
logger.info "Can't fetch '#{data[:url]}' (maybe no avatar available), http code: #{response.code}"
|
2014-12-01 07:32:35 +00:00
|
|
|
return
|
|
|
|
end
|
2015-05-04 18:58:28 +00:00
|
|
|
logger.info "Fetch '#{data[:url]}', http code: #{response.code}"
|
2014-12-01 07:32:35 +00:00
|
|
|
mime_type = 'image'
|
|
|
|
if data[:url] =~ /\.png/i
|
|
|
|
mime_type = 'image/png'
|
|
|
|
end
|
|
|
|
if data[:url] =~ /\.(jpg|jpeg)/i
|
|
|
|
mime_type = 'image/png'
|
|
|
|
end
|
|
|
|
if !data[:resize]
|
|
|
|
data[:resize] = {}
|
|
|
|
end
|
|
|
|
data[:resize][:content] = response.body
|
|
|
|
data[:resize][:mime_type] = mime_type
|
|
|
|
if !data[:full]
|
|
|
|
data[:full] = {}
|
|
|
|
end
|
|
|
|
data[:full][:content] = response.body
|
|
|
|
data[:full][:mime_type] = mime_type
|
|
|
|
end
|
|
|
|
|
|
|
|
# check if avatar need to be updated
|
|
|
|
record[:store_hash] = Digest::MD5.hexdigest( data[:resize][:content] )
|
|
|
|
if avatar_already_exists
|
|
|
|
return if avatar_already_exists.store_hash == record[:store_hash]
|
|
|
|
end
|
|
|
|
|
|
|
|
# store images
|
|
|
|
object_name = "Avatar::#{data[:object]}"
|
|
|
|
if data[:full]
|
|
|
|
store_full = Store.add(
|
2015-04-27 13:42:53 +00:00
|
|
|
object: "#{object_name}::Full",
|
|
|
|
o_id: data[:o_id],
|
|
|
|
data: data[:full][:content],
|
|
|
|
filename: 'avatar_full',
|
|
|
|
preferences: {
|
2014-12-01 07:32:35 +00:00
|
|
|
'Mime-Type' => data[:full][:mime_type]
|
|
|
|
},
|
2015-04-27 13:42:53 +00:00
|
|
|
created_by_id: data[:created_by_id],
|
2014-12-01 07:32:35 +00:00
|
|
|
)
|
|
|
|
record[:store_full_id] = store_full.id
|
|
|
|
record[:store_hash] = Digest::MD5.hexdigest( data[:full][:content] )
|
|
|
|
end
|
|
|
|
if data[:resize]
|
|
|
|
store_resize = Store.add(
|
2015-04-27 13:42:53 +00:00
|
|
|
object: "#{object_name}::Resize",
|
|
|
|
o_id: data[:o_id],
|
|
|
|
data: data[:resize][:content],
|
|
|
|
filename: 'avatar',
|
|
|
|
preferences: {
|
2014-12-01 07:32:35 +00:00
|
|
|
'Mime-Type' => data[:resize][:mime_type]
|
|
|
|
},
|
2015-04-27 13:42:53 +00:00
|
|
|
created_by_id: data[:created_by_id],
|
2014-12-01 07:32:35 +00:00
|
|
|
)
|
|
|
|
record[:store_resize_id] = store_resize.id
|
|
|
|
record[:store_hash] = Digest::MD5.hexdigest( data[:resize][:content] )
|
|
|
|
end
|
|
|
|
|
|
|
|
# update existing
|
|
|
|
if avatar_already_exists
|
|
|
|
avatar_already_exists.update_attributes( record )
|
|
|
|
avatar = avatar_already_exists
|
|
|
|
|
|
|
|
# add new one and set it as default
|
|
|
|
else
|
|
|
|
avatar = Avatar.create(record)
|
|
|
|
set_default_items(object_id, data[:o_id], avatar.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
avatar
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
set avatars as default
|
|
|
|
|
|
|
|
Avatar.set_default( 'User', 123, avatar_id )
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.set_default( object_name, o_id, avatar_id )
|
|
|
|
object_id = ObjectLookup.by_name( object_name )
|
2015-05-07 10:15:40 +00:00
|
|
|
avatar = Avatar.find_by(
|
2015-04-27 13:42:53 +00:00
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: o_id,
|
|
|
|
id: avatar_id,
|
2015-05-07 10:15:40 +00:00
|
|
|
)
|
2014-12-01 07:32:35 +00:00
|
|
|
avatar.default = true
|
|
|
|
avatar.save!
|
|
|
|
|
|
|
|
# set all other to default false
|
|
|
|
set_default_items(object_id, o_id, avatar_id)
|
|
|
|
|
|
|
|
avatar
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
remove all avatars of an object
|
|
|
|
|
|
|
|
Avatar.remove( 'User', 123 )
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.remove( object_name, o_id )
|
|
|
|
object_id = ObjectLookup.by_name( object_name )
|
|
|
|
Avatar.where(
|
2015-04-27 13:42:53 +00:00
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: o_id,
|
2014-12-01 07:32:35 +00:00
|
|
|
).destroy_all
|
|
|
|
|
|
|
|
object_name_store = "Avatar::#{object_name}"
|
|
|
|
Store.remove(
|
2015-04-27 13:42:53 +00:00
|
|
|
object: "#{object_name_store}::Full",
|
|
|
|
o_id: o_id,
|
2014-12-01 07:32:35 +00:00
|
|
|
)
|
|
|
|
Store.remove(
|
2015-04-27 13:42:53 +00:00
|
|
|
object: "#{object_name_store}::Resize",
|
|
|
|
o_id: o_id,
|
2014-12-01 07:32:35 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
remove one avatars of an object
|
|
|
|
|
|
|
|
Avatar.remove_one( 'User', 123, avatar_id )
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.remove_one( object_name, o_id, avatar_id )
|
|
|
|
object_id = ObjectLookup.by_name( object_name )
|
|
|
|
Avatar.where(
|
2015-04-27 13:42:53 +00:00
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: o_id,
|
|
|
|
id: avatar_id,
|
2014-12-01 07:32:35 +00:00
|
|
|
).destroy_all
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
return all avatars of an user
|
|
|
|
|
|
|
|
avatars = Avatar.list( 'User', 123 )
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.list(object_name, o_id)
|
|
|
|
object_id = ObjectLookup.by_name( object_name )
|
|
|
|
avatars = Avatar.where(
|
2015-04-27 13:42:53 +00:00
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: o_id,
|
2015-02-15 08:36:18 +00:00
|
|
|
).order( 'initial DESC, deletable ASC, created_at ASC, id DESC' )
|
2014-12-01 07:32:35 +00:00
|
|
|
|
2015-02-15 08:36:18 +00:00
|
|
|
# add initial avatar
|
2014-12-01 07:32:35 +00:00
|
|
|
add_init_avatar(object_id, o_id)
|
|
|
|
|
|
|
|
avatar_list = []
|
|
|
|
avatars.each do |avatar|
|
|
|
|
data = avatar.attributes
|
|
|
|
if avatar.store_resize_id
|
|
|
|
file = Store.find(avatar.store_resize_id)
|
2015-07-03 15:18:01 +00:00
|
|
|
data['content'] = "data:#{file.preferences['Mime-Type']};base64,#{Base64.strict_encode64( file.content )}"
|
2014-12-01 07:32:35 +00:00
|
|
|
end
|
|
|
|
avatar_list.push data
|
|
|
|
end
|
|
|
|
avatar_list
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
get default avatar image of user by hash
|
|
|
|
|
|
|
|
store = Avatar.get_by_hash( hash )
|
|
|
|
|
|
|
|
returns:
|
|
|
|
|
|
|
|
store object
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.get_by_hash(hash)
|
2015-05-07 10:15:40 +00:00
|
|
|
avatar = Avatar.find_by(
|
2015-04-27 13:42:53 +00:00
|
|
|
store_hash: hash,
|
2015-05-07 10:15:40 +00:00
|
|
|
)
|
2014-12-01 07:32:35 +00:00
|
|
|
return if !avatar
|
|
|
|
file = Store.find(avatar.store_resize_id)
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
get default avatar of user by user id
|
|
|
|
|
|
|
|
avatar = Avatar.get_default( 'User', user_id )
|
|
|
|
|
|
|
|
returns:
|
|
|
|
|
|
|
|
avatar object
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.get_default(object_name, o_id)
|
|
|
|
object_id = ObjectLookup.by_name( object_name )
|
2015-05-07 10:15:40 +00:00
|
|
|
Avatar.find_by(
|
2015-04-27 13:42:53 +00:00
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: o_id,
|
|
|
|
default: true,
|
2015-05-07 10:15:40 +00:00
|
|
|
)
|
2014-12-01 07:32:35 +00:00
|
|
|
end
|
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
def self.set_default_items(object_id, o_id, avatar_id)
|
|
|
|
avatars = Avatar.where(
|
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: o_id,
|
|
|
|
).order( 'created_at ASC, id DESC' )
|
|
|
|
avatars.each do |avatar|
|
|
|
|
next if avatar.id == avatar_id
|
|
|
|
avatar.default = false
|
|
|
|
avatar.save!
|
2014-12-01 07:32:35 +00:00
|
|
|
end
|
2015-04-27 14:56:32 +00:00
|
|
|
end
|
2014-12-01 07:32:35 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
def self.add_init_avatar(object_id, o_id)
|
2014-12-01 07:32:35 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
count = Avatar.where(
|
|
|
|
object_lookup_id: object_id,
|
|
|
|
o_id: o_id,
|
|
|
|
).count
|
|
|
|
return if count > 0
|
2014-12-01 07:32:35 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
Avatar.create(
|
|
|
|
o_id: o_id,
|
|
|
|
object_lookup_id: object_id,
|
|
|
|
default: true,
|
|
|
|
source: 'init',
|
|
|
|
initial: true,
|
|
|
|
deletable: false,
|
|
|
|
updated_by_id: 1,
|
|
|
|
created_by_id: 1,
|
|
|
|
)
|
|
|
|
end
|
2015-04-27 14:15:29 +00:00
|
|
|
end
|