Avatar provider plugin


(Jonas Friedmann) #1

Is there any plugin that extends the avatar providers?

I would like to add my own (in a schema like http://provider.com/avatars/%USERNAME%.png).


(Jonas Friedmann) #2

Okay, i just mess around with a bunch of code that i’ve found, but that doesn’t seem to work properly:

in my plugin.rb i use:

eval File.read("#{plugins_dir}/minecraft_avatars.rb")

and in minecraft_avatars.rb:

after_initialize do
  User.class_eval do
    def avatar_template
      "https://provider.com/avatars/#{self.username}?size=128"
    end
  end
end

Unfortunately, I have no idea if that’s proper code or outdated and impossible to run. Perhaps someone of you guys can help me out.


(Jens Maier) #3

I don’t think there is yet an extension point to add new avatar providers. You could rip out the letter avatars and replace them with minecraft avatars with:

class User
  class << self
    def letter_avatar_template(username)
      "/minecraft_avatar/#{username}.png"
    end
  end
end

Then mount a Rails engine under /minecraft_avatar that emits a HTTP 302 Found response and sends the useragent to the appropriate URL at provider.com.

Adapting the poll plugin’s engine should be fairly straight forward…


(Jonas Friedmann) #4

@elberet Thank you, this looks really promising.

Right now, I try to pass the “letter path”, and replaced my code with yours, like you suggested:

class User
  class << self
    def letter_avatar_template(username)
      "/minecraft_avatar/#{username}.png"
    end
  end
end

I assumed that now, the letter avatars should point to “http://[DOMAIN]/minecraft_avatar/”, but they still show up as “http://[DOMAIN]/letter_avatar/[…]”.

Or does this change only apply for new registrations because it’s somehow stored in the database?


(Jens Maier) #5

Where and how did you install that bit of Ruby code? If that is in a plugin, either use class ::User or wrap the snippet in a after_initialize do ... end block…


(Jonas Friedmann) #6

@elberet This is what I have so far:

after_initialize do
  class User
    class << self
      def letter_avatar_template(username)
        "/minecraft_avatar/#{username}.png"
      end
    end
  end
end

You can find the “whole” plugin over here at GitHub:

If I look at the source of http://forums.yeahwh.at/, they are still getting embedded from “/letter_avatar/[…]”.

Another question, should that affect all letter avatars? Or only the ones assigned to new registered users, while the plugin is enabled?


(Jens Maier) #7

Oh, don’t eval the file…

In plugin.rb:

after_initialize { load File.expand_path("../minecraft_avatars.rb", __FILE__) }

And in minecraft_avatars.rb, remove the after_initialize wrapper.


(Jonas Friedmann) #8

Just made the said adjustments but it stills comes up with the letters.

Can you check if I did anything correctly?

Also, sorry to bother you with this trivial tasks :confused:


(Jens Maier) #9

Oooooh, I should have had a closer look earlier on. You also need to monkey-patch a bit of JavaScript:

https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/models/user.js#L445-L463

The Ruby portion works fine, by the way. :slight_smile:


(Kane York) #10

So that’ll be:

Discourse.User.reopen({
avatarTemplate: function(username, uploadedAvatarId) {
  var url;

  if (uploadedAvatarId) {
    url = "/user_avatar/" +
          Discourse.BaseUrl +
          "/" +
          username.toLowerCase() +
          "/{size}/" +
          uploadedAvatarId + ".png";
  return Discourse.getURLWithCDN(url);
  } else {
    return "https://minotar.net/avatar/" +
          username.toLowerCase() +
          "/{size}.png";
  }

}
})

(Jonas Friedmann) #11

@riking Here’s what I have to far:

in plugin.rb:

after_initialize {
  load File.expand_path("../minecraft_avatars.rb", __FILE__)
}

register_asset "javascripts/minecraft_avatars.js", :server_side

in minecraft_avatars.rb:

User.class_eval do
  def avatar_template
    "/minecraft_avatar/#{username}.png"
  end
end 

in assets/javascripts/minecraft_avatars.js:

 (function () {
  Discourse.User.reopen({
    avatarTemplate: function(username, uploadedAvatarId) {
      var url;
      if (uploadedAvatarId) {
        url = "/user_avatar/" + Discourse.BaseUrl + "/" + username.toLowerCase() + "/{size}/" + uploadedAvatarId + ".png";
        return Discourse.getURLWithCDN(url);
      } else {
        return "https://crafatar.com/avatars/" + username.toLowerCase() + "?helm&size={size}";
      }
    }
  });
}).call(this);

But the letter avatars still show up. Any idea?


(Kane York) #12

Try replacing class_eval do with just class User

Also, do this:

 ./launcher enter app
rails c
User.last.avatar_template

(Jonas Friedmann) #13

User.last.avatar_template in the Rails console returned:

=> "/minecraft_avatar/Retro8.png"

The avatars however, still show the letters on the actual forums.

I also wonder, if we adjust the url to “/minecraft_avatar/Retro8.png”, don’t we have to somehow 302 redirect it to the actual external avatar URL, like @elberet suggested in the first reply?


(Jens Maier) #14

Hm, I have to admit that I don’t get it. I don’t know enough about Ember to be able to find out where it gets to avatar URL from.

Right now, my guess is that I’m missing something really stupid, such as a cache that needs to be flushed. :neutral_face:


(Jonas Friedmann) #15

@elberet No worries, I don’t understand even less. :smiley:

Thank you for your tips and assistance, though!


(Greg Swallow) #16

Could some code like this be used for a plugin or pull request that would grab the users facebook profile avatar if they signed up with facebook?


(Jonas Friedmann) #17

Okay. I noticed, whenever I try to create a new topic while the plugin is enabled I get the following errors:

PrettyText::JavaScriptError: Cannot call method 'reopen' of undefined in topics#show

and

PrettyText::JavaScriptError (PrettyText::JavaScriptError)

Any ideas?


(Jens Maier) #18

JavaScript assets loaded with the :server_side option are loaded into the server-side markdown parser used to cook posts. This JS environment is somewhat limited and does, for instance, not include the rest of the Discourse Ember app which is only loaded client-side.


(Jonas Friedmann) #19

I think I better stop to mess around with this “trial and error”-like on my (more or less productional) Discourse instance.

Since the plugin doesn’t work anyway (besides the error) :confused:

Thanks for your reply!


(Rafael dos Santos Silva) #20

Ok, I’m trying to do the exact same thing and it’s sad :sadpanda:

We already have a avatar service enterprise wide, and all our users have the same ID on the avatar service and on discourse so:

https://myportal.com/avatar/:discourseusername

We just want to make discourse use this URL everywhere the is an avatar.

Problems found so far:

  • Using SSO discourse tries to download and internalize the avatar, even when the option “download remote images to local” ain’t checked. This download fails, because discourse instance can`t reach avatar server.

  • Trying to monkey patch my way I can’t find the exact location.

Can someone help?