Repository: python-telegram-bot/python-telegram-bot

Issue:
[FEATURE] Filter for chat types
We currently have 

* `Filters.private` for private chats
* `Filters.updates.channel_post` for channel posts
* `Filters.group` for normal *and* supergroups

We're missing a standalone supergroup filter. Different ideas listed below. Personally, I'd go for 3.

# Proposal 1: Minimal invasive

* Add `Filters.supergroup`
* Document that `Filters.group` allows both

# Proposal 2: Adding flags

* Add a flag to `Filters.group` to specify, whether supergroups should be allowed or not

# Proposal 3: The full way

* Add `Filters.chat_type` that basically acts like `Filters.chat/user/via_bot`, just with `update.effective_message.chat.type`. We don't need to have `Filters.chat_type` updatetable, though IMHO. I really don't see a usecase for that.
* Add shortcuts for `private, channel, (super)group` as attributes to `Filters.chat_type` (similar to the `Filters.dice`)
* Make `Filters.private, group` shortcuts that work with `Filters.chat_type` and deprecate them (adding `TelegramDeprecationWarning` and documenting it)

By this, we would have two checks for `channel` (`Filters.chat_type.channel` and `Filters.update.channel_post(s)`), but especially is the latter allows to differentiate between original and edited channel post, I thinks both have their value.


Discussion:
I'll do the standalone supergroup filter, **Proposal 1**


Resolving patch:
diff --git a/telegram/ext/filters.py b/telegram/ext/filters.py
--- a/telegram/ext/filters.py
+++ b/telegram/ext/filters.py
@@ -19,6 +19,7 @@
 """This module contains the Filters for use with the MessageHandler class."""
 
 import re
+import warnings
 
 from abc import ABC, abstractmethod
 from threading import Lock
@@ -36,6 +37,8 @@
     'MergedFilter',
 ]
 
+from telegram.utils.deprecate import TelegramDeprecationWarning
+
 
 class BaseFilter(ABC):
     """Base class for all Filters.
@@ -949,19 +952,103 @@ class _Private(MessageFilter):
         name = 'Filters.private'
 
         def filter(self, message: Message) -> bool:
+            warnings.warn(
+                'Filters.private is deprecated. Use Filters.chat_type.private instead.',
+                TelegramDeprecationWarning,
+                stacklevel=2,
+            )
             return message.chat.type == Chat.PRIVATE
 
     private = _Private()
-    """Messages sent in a private chat."""
+    """
+    Messages sent in a private chat.
+
+    Note:
+        DEPRECATED. Use
+        :attr:`telegram.ext.Filters.chat_type.private` instead.
+    """
 
     class _Group(MessageFilter):
         name = 'Filters.group'
 
         def filter(self, message: Message) -> bool:
+            warnings.warn(
+                'Filters.group is deprecated. Use Filters.chat_type.groups instead.',
+                TelegramDeprecationWarning,
+                stacklevel=2,
+            )
             return message.chat.type in [Chat.GROUP, Chat.SUPERGROUP]
 
     group = _Group()
-    """Messages sent in a group chat."""
+    """
+    Messages sent in a group or a supergroup chat.
+
+    Note:
+        DEPRECATED. Use
+        :attr:`telegram.ext.Filters.chat_type.groups` instead.
+    """
+
+    class _ChatType(MessageFilter):
+        name = 'Filters.chat_type'
+
+        class _Channel(MessageFilter):
+            name = 'Filters.chat_type.channel'
+
+            def filter(self, message: Message) -> bool:
+                return message.chat.type == Chat.CHANNEL
+
+        channel = _Channel()
+
+        class _Group(MessageFilter):
+            name = 'Filters.chat_type.group'
+
+            def filter(self, message: Message) -> bool:
+                return message.chat.type == Chat.GROUP
+
+        group = _Group()
+
+        class _SuperGroup(MessageFilter):
+            name = 'Filters.chat_type.supergroup'
+
+            def filter(self, message: Message) -> bool:
+                return message.chat.type == Chat.SUPERGROUP
+
+        supergroup = _SuperGroup()
+
+        class _Groups(MessageFilter):
+            name = 'Filters.chat_type.groups'
+
+            def filter(self, message: Message) -> bool:
+                return message.chat.type in [Chat.GROUP, Chat.SUPERGROUP]
+
+        groups = _Groups()
+
+        class _Private(MessageFilter):
+            name = 'Filters.chat_type.private'
+
+            def filter(self, message: Message) -> bool:
+                return message.chat.type == Chat.PRIVATE
+
+        private = _Private()
+
+        def filter(self, message: Message) -> bool:
+            return bool(message.chat.type)
+
+    chat_type = _ChatType()
+    """Subset for filtering the type of chat.
+
+    Examples:
+        Use these filters like: ``Filters.chat_type.channel`` or
+        ``Filters.chat_type.supergroup`` etc. Or use just ``Filters.chat_type`` for all
+        chat types.
+
+    Attributes:
+        channel: Updates from channel
+        group: Updates from group
+        supergroup: Updates from supergroup
+        groups: Updates from group *or* supergroup
+        private: Updates sent in private chat
+    """
 
     class user(MessageFilter):
         """Filters messages to allow only those which are from specified user ID(s) or


Test patch:
diff --git a/tests/test_filters.py b/tests/test_filters.py
--- a/tests/test_filters.py
+++ b/tests/test_filters.py
@@ -24,6 +24,8 @@
 from telegram.ext import Filters, BaseFilter, MessageFilter, UpdateFilter
 import re
 
+from telegram.utils.deprecate import TelegramDeprecationWarning
+
 
 @pytest.fixture(scope='function')
 def update():
@@ -574,6 +576,10 @@ def test_private_filter(self, update):
         update.message.chat.type = 'group'
         assert not Filters.private(update)
 
+    def test_private_filter_deprecation(self, update):
+        with pytest.warns(TelegramDeprecationWarning):
+            Filters.private(update)
+
     def test_group_filter(self, update):
         assert not Filters.group(update)
         update.message.chat.type = 'group'
@@ -581,6 +587,29 @@ def test_group_filter(self, update):
         update.message.chat.type = 'supergroup'
         assert Filters.group(update)
 
+    def test_group_filter_deprecation(self, update):
+        with pytest.warns(TelegramDeprecationWarning):
+            Filters.group(update)
+
+    @pytest.mark.parametrize(
+        ('chat_type, results'),
+        [
+            (None, (False, False, False, False, False, False)),
+            (Chat.PRIVATE, (True, True, False, False, False, False)),
+            (Chat.GROUP, (True, False, True, False, True, False)),
+            (Chat.SUPERGROUP, (True, False, False, True, True, False)),
+            (Chat.CHANNEL, (True, False, False, False, False, True)),
+        ],
+    )
+    def test_filters_chat_types(self, update, chat_type, results):
+        update.message.chat.type = chat_type
+        assert Filters.chat_type(update) is results[0]
+        assert Filters.chat_type.private(update) is results[1]
+        assert Filters.chat_type.group(update) is results[2]
+        assert Filters.chat_type.supergroup(update) is results[3]
+        assert Filters.chat_type.groups(update) is results[4]
+        assert Filters.chat_type.channel(update) is results[5]
+
     def test_filters_user_init(self):
         with pytest.raises(RuntimeError, match='in conjunction with'):
             Filters.user(user_id=1, username='user')