New plugin: Stickers
This plugin implements XEP-0449 and allows the user to send and receive stickers. Sticker packs that are not published on the user's account can be uploaded and published on sign-in, if configured. The same holds true for stickers that are published on the user's account but not locally present, except that they are downloaded on sign-in. Animated stickers, though currently only GIFs, are also supported with the ability to turn off animations.
The button that shows a menu for selecting the sticker to send is also searchable and updates when a new sticker pack gets added. It searches for matchin in either a sticker's "description" (desc) or one of its "suggests".
When a sticker is not known, the sticker pack gets automatically downloaded and added. This, however, can be turned off. In that case, a button is shown that asks the user if the sticker pack should be downloaded.
As just deleting the folder containing the sticker pack does not delete it from the account, this plugin also features a UI for removing sticker packs:
There are, however, currently two problems:
- The stickers are always sent unencrypted. At least with OMEMO, all non-whitelisted tags are filtered out before sending.
- As a rework of the conversation view is currently in progress, I would have to rewrite the plugin a bit when that MR is merged.
I should note that the plugin does not support importing or creating sticker packs. For my testing purposes I have created a script that takes a JSON representation of a sticker pack - that this plugin uses internally - and updates it so that the plugin can work with it. I feel like it is out of scope of the plugin, or at least of this first MR.
Under Linux the plugin requires stickers to be located at ~/.local/share/gajim/plugins_data/stickers/<sticker pack ID>/<sticker file>
. The folder must contain a info.json file that describes the sticker pack and looks like this:
{
"id": "0c58051a78fcd4ecf982f136",
"name": "A sticker pack",
"summary": "A description",
"stickers": [
{
"type": "image/png",
"hashes": [
{
"algo": "sha-256",
"value": "8b76e01a4cd9ef8b3d63541459b1718b62c6073271b4e14cd0a9d3155964f13b"
}
],
"size": "14015",
"dimension": "113x110",
"desc": ":grin:",
"suggests": [":blobgrin:"],
"filename": "grin.png",
"url": ""
},
[...]
]
}
The URL attribute of a sticker can be left empty as the plugin updates it automatically when the sticker pack has been published.
I tested this plugin on two Linux machines and it works. It requires a Gajim version newer than a290db02
.
Merge request reports
Activity
- Resolved by Alexander
- Resolved by Daniel Brötzmann
- Resolved by Daniel Brötzmann
- Resolved by Daniel Brötzmann
- Resolved by Daniel Brötzmann
- Resolved by Daniel Brötzmann
- Resolved by Daniel Brötzmann
- Resolved by Daniel Brötzmann
Nice work! I’m really looking forward for this :)
Since gajim!733 (closed) won’t be part of Gajim 1.3, this is nothing to worry about at this point.
@PapaTutuWawa would you be so kind and provide an example sticker pack?
Edited by Daniel Brötzmannadded 1 commit
- 69679f12 - [stickers] Disallow sending stickers when using encryption
- Resolved by Daniel Brötzmann
@wurstsalat I created a very simple test sticker pack based on the Gajim logo with three stickers.
Just un-tar it into
~/.local/share/gajim/plugins_data/stickers
(Assuming Linux) and restart Gajim. Not sure if I already mentioned this, but I think a button to reload the sticker packs would probably be nice.
added 5 commits
Toggle commit list- Resolved by Alexander
- Resolved by Alexander
- Resolved by Alexander
- Resolved by Alexander
added 5 commits
- b3e66ee0 - [stickers] Various UI improvements
- b6dd6219 - [stickers] Refactor StickersButton to work with models
- 2d88f372 - [stickers] Ask if the user really wants to reload all sticker packs
- fea91a10 - [stickers] Some small code improvements
- a2ece3b0 - [stickers] To ease my mind, check for another path escape on download
Toggle commit listSo I now did the following things:
- I moved the entire UI where stickers are shown to using models. Maybe I went a bit ham, but I implemented a proxy model for filtering, as I was not sure whether I could just depend on libdazzle for such a model.
- I added a button to show the folder containing all sticker packs.
- Not uploaded stickers now show a button to upload and publish them. Additionally, if a user tries to send a sticker from a non-uploaded sticker, a prompt will show up asking if the sticker pack should be uploaded.
Yeah, I agree. It is just the first icon I found while scrolling through the icon list in Glade that somewhat implied the action. All other icons, including promising ones like
document-send
ordocument-send-symbolic
(Based on the description from the opendesktop spec:[...] Should be an arrow pointing up and away from a hard disk.
) don't make me feel like I am uploading a file. This, however, may also be an issue with my setup as I am on KDE.fails for me on first start
Traceback (most recent call last): File "/home/lovetox/projects/gajim/gajim/plugins/pluginmanager.py", line 290, in add_plugin plugin_obj = plugin_class() File "/home/lovetox/projects/gajim/gajim/plugins/gajimplugin.py", line 177, in __init__ self.init() File "/home/lovetox/.local/share/gajim/plugins/stickers/plugin.py", line 204, in init self.config_dialog = StickersConfigDialog(self) File "/home/lovetox/projects/gajim/gajim/plugins/gui.py", line 324, in __init__ self.init() File "/home/lovetox/.local/share/gajim/plugins/stickers/gtk/config.py", line 50, in init getattr(self._ui, setting).set_active(self.plugin.config[setting.upper()]) File "/home/lovetox/projects/gajim/gajim/plugins/gajimplugin.py", line 219, in __getitem__ self.data[key] = self.plugin.config_default_values[key][0] KeyError: 'DOWNLOAD_NEW'
Are you aware that the module in the modules folder get instantiated for every account in Gajim? Did you think about what happens when in Gajim more than one account is active?
Normally you would want account specific data to be handled and stored in the sticker_module.py. Right now you send events to the plugin.py and store it there. This makes it necessary that you have multiple dict stores with the account as key and need to handle stuff like new accounts getting added and other accounts vanish etc. Did you have a specific reason why to store the account specific packs there?
Are you aware that the module in the modules folder get instantiated for every account in Gajim?
I would say kinda yes, kinda no. This code is mainly based on an earlier prototype before the XEP even existed. There I did much less of this state tracking than now.
However, I would argue that my approach has the benefit - that I am going for - that a sticker pack is only downloaded once, even if multiple accounts exist. I have no concept of account specific sticker packs. Most of the state variables are just so I know what I have done and what not, e.g. preventing that we download every sticker pack, even if we did not even request it.
But looking at the module again, I could probably move some code from the plugin to the module.
I also thought that the upload of sticker packs should maybe happen per account to prevent leaking things like the HTTP host of other accounts, but initially I wanted to bundle the uploads together, like I did with the download.
Did you think about what happens when in Gajim more than one account is active?
Yes. I have multiple accounts linked to my Gajim, meaning that I do think about those interactions.
plugin.py itself should probably only be the interface to Gajim.
- Handle events that originated from Gajim (sign-in etc)
- Offer public methods which can be called from other plugins or Gajim
the module should handle everything else.
- Uploading to the account
- Downloading from the account
- Reacting to stanza events
- Holding any account specific data
Also it rather seems forced that you inform plugin.py via many events of everything that happens in the module.
This should not mean you cant have a single store for all sticker packs. init the store in plugin.py, and afterwards simply modify the store from the module, you already have a ref to the plugin there and with that a ref to the store.
What i like to do for something like that is using a Singleton, checkout AvatarStorage in avatar.py in Gajim. Singleton means you can simply do
from sticker.store import Store
and have it available everywhere without passing references around.you binding to the decrypted-message-received GUI signal from Gajim, its meant as GUI signal meaning something in the GUI should happen.
Its better you bind in the module via StanzaHandler to the message stanza with according priority, look for example in the omemo plugin module on how to use it.
Yeah, the age and differences in this XEP and my own thought up really show in the code now. I will try and do that.
Edited by Alexander
For now please remove #max_items from publish options, ejabberd does not support this field in publish options, and its a very widespread server.
as workaround you could retrive the node configuration, and simply check what max_items is set to, and if you dont like it push a new configurion. see Pubsub module
- set_node_configuration
- get_node_configuration
Callback seems broken after upload
Traceback (most recent call last): File "/home/lovetox/projects/gajim/gajim/common/ged.py", line 101, in raise_event if handler(*args, **kwargs): File "/home/lovetox/.local/share/gajim/plugins/stickers/plugin.py", line 365, in _on_sticker_pack_uploaded self._model_replace(StickerPackObject.from_sticker_pack(pack)) File "/home/lovetox/.local/share/gajim/plugins/stickers/plugin.py", line 319, in _model_replace index = self._model_remove(pack.id_) File "/home/lovetox/.local/share/gajim/plugins/stickers/plugin.py", line 306, in _model_remove for index_ in range(model.get_n_items()): NameError: name 'model' is not defined
mentioned in issue gajim#9315
Now that I have got time again, I started working on this plugin again. When publishing on the PubSub node, the plugin now first checks if the max_items property is set to a sufficiently high number for all sticker packs and if not, it reconfigures the node.
What I still have to do before I would say that I'm "done", is the following:
- Find a better icon for the "upload and publish sticker pack" button
- Test some more! I think that there are issues with Windows, but I am not sure about that one
- Maybe add a setting to set the access model on the PubSub node
added 6 commits
Toggle commit listI have now implemented a setting for setting the access model of the stickers PubSub node and found a better icon. This plugin now implements everything from XEP-0449, except for the sharing of sticker packs and explicit dealing with restricted sticker packs, i.e. you can use them just like any other sticker pack.
I also noticed that I left in a local file with which I have been generating the sticker packs' info.json file. I will remove that from the MR.
The code has reached a point at which I would say that this plugin has all features I wanted it to have and that it is ready for testing outside of my own use.
Except for bug fixes and code style fixes, which I plan on doing, I probably won't add any more code.