Description
This is kind of a meta issue, but I felt like it's more appropriate and convenient to discuss it here than in the dev chat.
Disclaimer
I know, that this is quite a wall of text. Still, I'd appreciate any feedback, both from the maintainers/developers and the users/potential contributers perspective. I'm sure that I haven't covered everything and that there are other, more elegant solutions to the problems I list, which I simply don't see.
The Problem
We have sometimes have feature requests/PRs that are reasonable for some applications but kind of too specific for a general purpose library.
Examples (from my point of view) are #854 (extract_url
helper) #1861 (forward messages by "copying" them), #1702 (handler for inline menus based on CH. There are also older approaches to that), maybe #1911 as well (read descriptions from CommandHandlers and use them with Bot.set_my_commands
)
Right now, we have mostly have to reject those, because we simply don't have the resources to maintain those contributions.
Parts of the code snippets section in the wiki also fall into this category.
Proposal: Contribution Repository
The idea of a contribution repository has been discussed in the dev chat before. The general idea is to add a repository python-telegram-bot-contrib/plugins
or whatever, where such "reasonable but out of scope" features can be collected.
Personally, I find the idea appealing. That way we can give users a way of exchanging pieces of code that may be usefull for others and also have some "experimental" features that we don't want to have to maintain.
Alternatives:
-
We already have a
/contrib
directory in the main repo. However opening this to the contributions described above will probably hard to tell "important" prs/issues from contribution-ones. Also the git-log will likely become messy and we might be pressured into releasing quicker than we want to. -
A low-effort alternative would be to add a wiki page to just gather links to such things. Everyone could maintain their own plugin and add a link it there. While this means nearly no maintainance work, this also means that the listed resources most likely will come with a lower code standard and will probably not have a uniform integration interface (see below)
Problems
If we decide that a contrib repo is a good thing to have, there are some issues to think about
Shipping
How do we install the contrib repo?
- Ship it as regular package to be installed by
pip
. But how often? Contributers will likely expect a contrib package to be released much more frequently than ptb. Do we release after every commit? Once a month? - Make people install master.
pip
can do that, so that's not really an issue. This seem unsatisfactory at first glance. On the other hand, people installing from a contrib repo should (should!) know their way around PTB and Python in general. Also it takes away a lot of maintainance work. The Changelog could be a separete one for every contribution and be updated on the fly.
Architecture
The contrib repo should be designed such that all features are separated from each other. So if one feature is buggy, the others will still work. My suggestion would be to have every contribution in a single file/module, so we could do stuff like
from telegram-contrib import feature-a
# from telegram-contrib import feature-b # skip this one, this is buggy
from telegram-contrib import feature-c
Integration with PTB
This one is a real problem in my eyes. We'll want to make it simple to use the contrib repo with PTB, while making little to no changes with PTB itself. Let's assume we have installed the contrib repo as telegram-contrib
package. There are different situations:
-
Additional functions, handlers, ect. We can just import them like
from telegram-contrib import MyHandler
and be done with it
-
Additions to existing classes, e.g. Add extract_urls-helper #854 and #1861 would make sense as class methods of
Message
. This is a bit trickier, sinceMessage.de_json
is called on receiving updates. One could go forUpdater(..., use_contrib_message=True)
or something. However that poses two difficulties:- We have to make changes to ptb. Meh.
- Add extract_urls-helper #854 and #1861 will likely (see above) be implemented independently from each other, so we'd have decide, which contrib
Message
to use. Using both would become a hassle.
Another approach could be to do
from telegram import Message fun = Message.forward def forward(*args, **kwargs): fun(*args, **kwargs) # some stuff Message.forward = foward
and then
from telegram import Message from telegram-contrib import patch-forward ...
Kind of hacky, but it could do the trick.
Edit: Past v13 this will play poorly with type hinting …
-
Then there is stuff, that not like a "standalone" thing, but only really makes sense when integrated in the whole architecture of ptb, like Roles #1789. This could surely be done as described as above, but that could become ugly quickly…
Maintainance
Who will be maintainer and developer in this repo? Contributions should be reviewed (even if not as thoroughly as with PTB), so I guess merging would be the job of the PTB maintainers.
However, answering to issues related to their own contributions could be understood as the responsibility of the contributers themself, so one could argue that every contributer should be promoted to developer.
In any way, it would be a good idea to have someone as developer, who is not actively involved in the main repo, imho.
Where to draw the line?
Pretty much linked with the maintainance question. Who decides, what is goes intro contribution and what goes into PTB? What is general purpose, what isn't?
Documentation
I'd suggest to host documentation for the contrib repo on rtd independently from PTB. Using just the wiki is also a vailable way, but using only the wiki we don't really have a way to enforce contributers to document their features. The docs don't have to be as polished as the ones for PTB, but they should state what a feature can and cannot do and what known issues are.
A Changelog could be kept for every feature separately, which would be especially usefull in the "install from master" option described above.