trabajo-afectivo/app/models/avatar.rb

423 lines
10 KiB
Ruby
Raw Normal View History

2016-10-19 03:11:36 +00:00
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
2014-12-01 07:32:35 +00:00
class Avatar < ApplicationModel
2018-04-12 14:57:37 +00:00
belongs_to :object_lookup
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-12-14 16:09:09 +00:00
object: 'User',
o_id: user.id,
url: 'somebody@example.com',
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')
2016-12-02 11:24:00 +00:00
return if data[:url].blank?
2014-12-01 07:32:35 +00:00
Avatar.add(
object: data[:object],
o_id: data[:o_id],
url: data[:url],
source: 'zammad.com',
deletable: false,
updated_by_id: 1,
created_by_id: 1,
2014-12-01 07:32:35 +00:00
)
end
=begin
2016-10-06 16:59:23 +00:00
add avatar by upload
2014-12-01 07:32:35 +00:00
Avatar.add(
2015-12-14 16:09:09 +00:00
object: 'User',
o_id: user.id,
default: true,
full: {
content: '...',
mime_type: 'image/png',
2014-12-01 07:32:35 +00:00
},
2015-12-14 16:09:09 +00:00
resize: {
content: '...',
mime_type: 'image/png',
2014-12-01 07:32:35 +00:00
},
2015-12-14 16:09:09 +00:00
source: 'web',
2016-10-06 16:59:23 +00:00
deletable: true,
updated_by_id: 1,
created_by_id: 1,
)
add avatar by url
Avatar.add(
object: 'User',
o_id: user.id,
default: true,
url: ...,
source: 'web',
deletable: true,
2015-12-14 16:09:09 +00:00
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]
2016-03-08 06:32:58 +00:00
object_id = ObjectLookup.by_name(data[:object])
2014-12-01 07:32:35 +00:00
end
2015-02-15 08:36:18 +00:00
# add initial avatar
_add_init_avatar(object_id, data[:o_id])
2014-12-01 07:32:35 +00:00
record = {
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
2016-12-02 11:24:00 +00:00
if data[:source].present?
avatar_already_exists = Avatar.find_by(
object_lookup_id: object_id,
o_id: data[:o_id],
source: data[:source],
)
2014-12-01 07:32:35 +00:00
end
# fetch image based on http url
2017-10-20 13:32:01 +00:00
if data[:url].present?
if data[:url].class == Tempfile
logger.info "Reading image from tempfile '#{data[:url].inspect}'"
content = data[:url].read
filename = data[:url].path
mime_type = 'image'
if filename.match?(/\.png/i)
mime_type = 'image/png'
end
if filename.match?(/\.(jpg|jpeg)/i)
mime_type = 'image/jpeg'
end
data[:resize] ||= {}
data[:resize][:content] = content
data[:resize][:mime_type] = mime_type
data[:full] ||= {}
data[:full][:content] = content
data[:full][:mime_type] = mime_type
elsif data[:url].to_s.match?(%r{^https?://})
url = data[:url].to_s
2017-10-20 13:32:01 +00:00
# check if source ist already updated within last 2 minutes
if avatar_already_exists&.source_url == url
2017-10-20 13:32:01 +00:00
return if avatar_already_exists.updated_at > 2.minutes.ago
end
# twitter workaround to get bigger avatar images
# see also https://dev.twitter.com/overview/general/user-profile-images-and-banners
if url.match?(%r{//pbs.twimg.com/}i)
url.sub!(/normal\.(png|jpg|gif)$/, 'bigger.\1')
2017-10-20 13:32:01 +00:00
end
# fetch image
response = UserAgent.get(
url,
2017-10-20 13:32:01 +00:00
{},
{
open_timeout: 4,
read_timeout: 6,
2017-10-20 13:32:01 +00:00
total_timeout: 6,
},
)
if !response.success?
logger.info "Can't fetch '#{url}' (maybe no avatar available), http code: #{response.code}"
2017-10-20 13:32:01 +00:00
return
end
logger.info "Fetchd image '#{url}', http code: #{response.code}"
2017-10-20 13:32:01 +00:00
mime_type = 'image'
if url.match?(/\.png/i)
2017-10-20 13:32:01 +00:00
mime_type = 'image/png'
end
if url.match?(/\.(jpg|jpeg)/i)
2017-10-20 13:32:01 +00:00
mime_type = 'image/jpeg'
end
data[:resize] ||= {}
2017-10-20 13:32:01 +00:00
data[:resize][:content] = response.body
data[:resize][:mime_type] = mime_type
data[:full] ||= {}
data[:full][:content] = response.body
data[:full][:mime_type] = mime_type
# try zammad backend to find image based on email
elsif data[:url].to_s.match?(URI::MailTo::EMAIL_REGEXP)
url = data[:url].to_s
2017-10-20 13:32:01 +00:00
# check if source ist already updated within last 3 minutes
if avatar_already_exists&.source_url == url
2017-10-20 13:32:01 +00:00
return if avatar_already_exists.updated_at > 2.minutes.ago
end
# fetch image
image = Service::Image.user(url)
2017-10-20 13:32:01 +00:00
return if !image
2017-10-20 13:32:01 +00:00
data[:resize] = image
data[:full] = image
end
2014-12-01 07:32:35 +00:00
end
# check if avatar need to be updated
2017-10-20 13:32:01 +00:00
if data[:resize].present? && data[:resize][:content].present?
record[:store_hash] = Digest::MD5.hexdigest(data[:resize][:content])
2017-11-23 08:09:44 +00:00
if avatar_already_exists&.store_hash == record[:store_hash]
avatar_already_exists.touch # rubocop:disable Rails/SkipsModelValidations
2017-10-20 13:32:01 +00:00
return avatar_already_exists
end
2014-12-01 07:32:35 +00:00
end
# store images
object_name = "Avatar::#{data[:object]}"
2017-10-20 13:32:01 +00:00
if data[:full].present?
2014-12-01 07:32:35 +00:00
store_full = Store.add(
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]
},
created_by_id: data[:created_by_id],
2014-12-01 07:32:35 +00:00
)
record[:store_full_id] = store_full.id
2016-03-08 06:32:58 +00:00
record[:store_hash] = Digest::MD5.hexdigest(data[:full][:content])
2014-12-01 07:32:35 +00:00
end
2017-10-20 13:32:01 +00:00
if data[:resize].present?
2014-12-01 07:32:35 +00:00
store_resize = Store.add(
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]
},
created_by_id: data[:created_by_id],
2014-12-01 07:32:35 +00:00
)
record[:store_resize_id] = store_resize.id
2017-10-20 13:32:01 +00:00
record[:store_hash] = Digest::MD5.hexdigest(data[:resize][:content])
2014-12-01 07:32:35 +00:00
end
2017-10-20 13:32:01 +00:00
return if record[:store_resize_id].blank? || record[:store_hash].blank?
2014-12-01 07:32:35 +00:00
# update existing
if avatar_already_exists
avatar_already_exists.update!(record)
2014-12-01 07:32:35 +00:00
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
2015-12-14 16:09:09 +00:00
Avatar.set_default('User', 123, avatar_id)
2014-12-01 07:32:35 +00:00
=end
2016-03-08 06:32:58 +00:00
def self.set_default(object_name, o_id, avatar_id)
object_id = ObjectLookup.by_name(object_name)
avatar = Avatar.find_by(
object_lookup_id: object_id,
o_id: o_id,
id: avatar_id,
)
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
2015-12-14 16:09:09 +00:00
Avatar.remove('User', 123)
2014-12-01 07:32:35 +00:00
=end
2015-12-14 16:09:09 +00:00
def self.remove(object_name, o_id)
object_id = ObjectLookup.by_name(object_name)
2014-12-01 07:32:35 +00:00
Avatar.where(
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(
object: "#{object_name_store}::Full",
o_id: o_id,
2014-12-01 07:32:35 +00:00
)
Store.remove(
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
2015-12-14 16:09:09 +00:00
Avatar.remove_one('User', 123, avatar_id)
2014-12-01 07:32:35 +00:00
=end
2015-12-14 16:09:09 +00:00
def self.remove_one(object_name, o_id, avatar_id)
object_id = ObjectLookup.by_name(object_name)
2014-12-01 07:32:35 +00:00
Avatar.where(
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
2015-12-14 16:09:09 +00:00
avatars = Avatar.list('User', 123)
2014-12-01 07:32:35 +00:00
avatars = Avatar.list('User', 123, no_init_add_as_boolean) # per default true
2014-12-01 07:32:35 +00:00
=end
def self.list(object_name, o_id, no_init_add_as_boolean = true)
2015-12-14 16:09:09 +00:00
object_id = ObjectLookup.by_name(object_name)
2014-12-01 07:32:35 +00:00
avatars = Avatar.where(
object_lookup_id: object_id,
o_id: o_id,
2015-12-14 16:09:09 +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
if no_init_add_as_boolean
_add_init_avatar(object_id, o_id)
end
2014-12-01 07:32:35 +00:00
avatar_list = []
avatars.each do |avatar|
data = avatar.attributes
if avatar.store_resize_id
file = Store.find(avatar.store_resize_id)
2015-12-14 16:09:09 +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
2015-12-14 16:09:09 +00:00
store = Avatar.get_by_hash(hash)
2014-12-01 07:32:35 +00:00
returns:
store object
=end
def self.get_by_hash(hash)
avatar = Avatar.find_by(
store_hash: hash,
)
2014-12-01 07:32:35 +00:00
return if !avatar
Store.find(avatar.store_resize_id)
2014-12-01 07:32:35 +00:00
end
=begin
get default avatar of user by user id
2015-12-14 16:09:09 +00:00
avatar = Avatar.get_default('User', user_id)
2014-12-01 07:32:35 +00:00
returns:
avatar object
=end
def self.get_default(object_name, o_id)
2015-12-14 16:09:09 +00:00
object_id = ObjectLookup.by_name(object_name)
Avatar.find_by(
object_lookup_id: object_id,
o_id: o_id,
default: true,
)
2014-12-01 07:32:35 +00:00
end
def self.set_default_items(object_id, o_id, avatar_id)
avatars = Avatar.where(
object_lookup_id: object_id,
o_id: o_id,
2015-12-14 16:09:09 +00:00
).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
end
2014-12-01 07:32:35 +00:00
def self._add_init_avatar(object_id, o_id)
2014-12-01 07:32:35 +00:00
count = Avatar.where(
object_lookup_id: object_id,
o_id: o_id,
).count
2016-10-24 21:59:18 +00:00
return if count.positive?
2014-12-01 07:32:35 +00:00
object_name = ObjectLookup.by_id(object_id)
return if !object_name.constantize.exists?(id: o_id)
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
end