How to Set Avatar via Plugin

I am using the Plugin SDK with the test_plugin example.
Is it possible to change the user’s avatar with a plugin?
I found this old post TeamSpeak - Official TeamSpeak Community Forum where at the end there is described a possible way of achieving this.
However, as far as I understand it in order to change client attributes you have to use ts3client_setClientSelfVariableAsInt with the appropiate ClientProperties flag.
However I can’t find anything related to Avatars in these flags.
Am I missing something?
Is there a better way of doing this, it seems like such a trivial task but I can’t find anything else in the documentation.

It is exactly as ScP wrote back then:

ts3Functions.setClientSelfVariableAsString(sCHID, CLIENT_FLAG_AVATAR, "file_name_or_smthn");
1 Like

Hi, thanks for your reply.
Where can I find CLIENT_FLAG_AVATAR ?
Can you show me or give me the value, these are all the Client Flags I can find in public.definitions.h
and also the ones that are in the documentation under Retrieve and store information -> Client information-> Information related to own client.

enum ClientProperties { CLIENT_UNIQUE_IDENTIFIER = 0, //automatically up-to-date for any client "in view", can be used to identify this particular client installation CLIENT_NICKNAME, //automatically up-to-date for any client "in view" CLIENT_VERSION, //for other clients than ourself, this needs to be requested (=> requestClientVariables) CLIENT_PLATFORM, //for other clients than ourself, this needs to be requested (=> requestClientVariables) CLIENT_FLAG_TALKING, //automatically up-to-date for any client that can be heard (in room / whisper) CLIENT_INPUT_MUTED, //automatically up-to-date for any client "in view", this clients microphone mute status CLIENT_OUTPUT_MUTED, //automatically up-to-date for any client "in view", this clients headphones/speakers/mic combined mute status CLIENT_OUTPUTONLY_MUTED, //automatically up-to-date for any client "in view", this clients headphones/speakers only mute status CLIENT_INPUT_HARDWARE, //automatically up-to-date for any client "in view", this clients microphone hardware status (is the capture device opened?) CLIENT_OUTPUT_HARDWARE, //automatically up-to-date for any client "in view", this clients headphone/speakers hardware status (is the playback device opened?) CLIENT_INPUT_DEACTIVATED, //only usable for ourself, not propagated to the network CLIENT_IDLE_TIME, //internal use CLIENT_DEFAULT_CHANNEL, //only usable for ourself, the default channel we used to connect on our last connection attempt CLIENT_DEFAULT_CHANNEL_PASSWORD, //internal use CLIENT_SERVER_PASSWORD, //internal use CLIENT_META_DATA, //automatically up-to-date for any client "in view", not used by TeamSpeak, free storage for sdk users CLIENT_IS_MUTED, //only make sense on the client side locally, "1" if this client is currently muted by us, "0" if he is not CLIENT_IS_RECORDING, //automatically up-to-date for any client "in view" CLIENT_VOLUME_MODIFICATOR, //internal use CLIENT_VERSION_SIGN, //sign CLIENT_SECURITY_HASH, //SDK use, not used by teamspeak. Hash is provided by an outside source. A channel will use the security salt + other client data to calculate a hash, which must be the same as the one provided here. CLIENT_ENDMARKER, }; Code tags don’t seem to work, sorry…

But so I understand correctly, this is the way to set one’s avatar?
If so, do you know what is meant with avatar_<client_base64HashClientUID> ?
What is base64HashClientUID?

Yes

Can’t tell you right now but maybe later.

1 Like

Oh wow, I didn’t even notice the public_rare_definitions.h
I assumed the only ClientProperties where the ones in the documentation / public_definitions.h

Ok, so now after setting CLIENT_AVATAR_FLAG and flushing the changes (which all work, I always check return code), my Avatar becomes a red default image with a 404.
If I try to append my clientID to the filename: avatar_1982.jpeg, I get this in the logs:

2020-11-02 22:44:59.831053|DEBUG   |SB            |   |onUpdateClientEvent: serverId = 1, clientId = 1982, invokerID = 0, invokerName = "", invokerUID = ""
2020-11-02 22:43:07.877674|WARNING |ClientUI      |   |Error, avatar md5 does not match. Cannot display image.avatar_1982.jpeg <-> 1e0d208b1ef2760c3fdf22786328b370

So I tried to use the hash it was giving me, also didn’t work.

 2020-11-02 22:45:00.580073|WARNING |ClientUI      |   |Error, avatar md5 does not match. Cannot display image.avatar_1e0d208b1ef2760c3fdf22786328b370.jpeg <-> 1e0d208b1ef2760c3fdf22786328b370

I’m unsure what hash is failing. I tried to see if it was expecting my hashed clientID, but the MD5 hash of 1982 is fb87582825f9d28a8d42c5e5e5e8b23d which also didn’t work.
I even tried not using any extension for the filename, since that’s the way it’s written in the original post, nothing.
I don’t think the extension is the problem though, since one time I got this in the logs:

2020-11-02 22:44:54.360447|INFO    |UIHelpers     |   |Supported image formats: *.bmp *.gif *.jpeg *.jpg *.pbm *.pgm *.png *.ppm *.svg *.svgz *.xbm *.xpm

I’m currently too tired to understand this, but I found this:

  const hex = 'abcdefghijklmnop';
  const base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  
  function getFilename()
  {
    var s = "clientuuidherelikethis=";
    var bin = '';
    for ( var i = 0; i < 27; i++) // last character is always "="
    {
      var c = base64.indexOf(s.charAt(i));
      bin += String((c >> 5)) + String((c >> 4) % 2) + String((c >> 3) % 2) + String((c >> 2) % 2) + String((c >> 1) % 2) + String(c % 2);
    }
    var out = 'avatar_';
    for ( var i = 0; i < 40; i++)
    {
      out += hex.charAt(Number(bin.charAt(i*4)) * 8 + Number(bin.charAt(i*4+1)) * 4 + Number(bin.charAt(i*4+2)) * 2 + Number(bin.charAt(i*4+3)));
    }
    filename.value = out;
  }

The file needs to be named exactly: avatar_output without any extention.
Then generate the md5 checksum for that file and set it as the client_flag_avatar.

1 Like

Thank you very much for your help, I managed to get it working.
As you said the file has to be named avatar_ followed by the base64 encoding of the “CLIENTID=” (replace CLIENTID with your clientID).
I don’t think there is anything special about the base64 encoding you posted, I used a simple online encoder and it worked.
For the md5 as you said setting the md5 hash of the image file as CLIENT_FLAG_AVATAR is correct.
With this I can set my Avatar programmatically, it’s just the size that is different than setting it with normal “Set Avatar”, but I’ll look more into that later.