Repository: aiogram/aiogram
Pull request #1049 (2022-10-30 18:25:54)

add method for get user mention
# Description

<!--
Please include a summary of the change.

e.g. Add a new awesome feature or Fix documentation typo.

Please also include relevant motivation and context.
If you are fixing an issue, specify what issue is fixed.

e.g. Fix #12345
-->

I'm tired of writing like this
```python
html.link(message.from_user.full_name, f'tg://user?id={message.from_user.id}')
```
so i did it pull request

## Type of change

<!--
Please delete options that are not relevant.
-->

- adding method to get to get mention of user


# Checklist:

<!--
Please delete options that are not relevant to your change.
-->

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have added tests that prove my fix is effective or that my feature works as expected
- [x] New and existing unit tests pass locally with my changes
- [x] My changes generate no new warnings or errors
- [x] My changes are compatible with minimum requirements of the project
- [x] I have made corresponding changes to the documentation

github-actions[bot]: # :x: Changelog is required!

You need to add a brief description of the changes to the `CHANGES` directory.

For example, you can run `towncrier create <issue>.<type>` to create a file in the change directory and then write a description on that file.

Read more at [Towncrier docs](https://towncrier.readthedocs.io/en/latest/quickstart.html#creating-news-fragments)
codecov[bot]: # [Codecov](https://codecov.io/gh/aiogram/aiogram/pull/1049?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) Report
> Merging [#1049](https://codecov.io/gh/aiogram/aiogram/pull/1049?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) (293186c) into [dev-3.x](https://codecov.io/gh/aiogram/aiogram/commit/67fbee454a69d2a83373c7b9ffa70c2e20778979?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) (67fbee4) will **decrease** coverage by `0.03%`.
> The diff coverage is `75.00%`.

[![Impacted file tree graph](https://codecov.io/gh/aiogram/aiogram/pull/1049/graphs/tree.svg?width=650&height=150&src=pr&token=cFqEr3p9MX&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram)](https://codecov.io/gh/aiogram/aiogram/pull/1049?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram)

```diff
@@             Coverage Diff             @@
##           dev-3.x    #1049      +/-   ##
===========================================
- Coverage   100.00%   99.96%   -0.04%     
===========================================
  Files          302      302              
  Lines         8158     8170      +12     
===========================================
+ Hits          8158     8167       +9     
- Misses           0        3       +3     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `99.96% <75.00%> (-0.04%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/aiogram/aiogram/pull/1049?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) | Coverage Δ | |
|---|---|---|
| [aiogram/types/user.py](https://codecov.io/gh/aiogram/aiogram/pull/1049/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS90eXBlcy91c2VyLnB5) | `93.02% <75.00%> (-6.98%)` | :arrow_down: |


Patch:
diff --git a/CHANGES/1049.feature.rst b/CHANGES/1049.feature.rst
new file mode 100644
index 00000000..c54bef04
--- /dev/null
+++ b/CHANGES/1049.feature.rst
@@ -0,0 +1,4 @@
+Added following methods to ``User`` class:
+
+- ``User.mention_markdown(...)``
+- ``User.mention_html(...)``
diff --git a/aiogram/fsm/storage/redis.py b/aiogram/fsm/storage/redis.py
index f5f9a0d6..2d8d5076 100644
--- a/aiogram/fsm/storage/redis.py
+++ b/aiogram/fsm/storage/redis.py
@@ -84,7 +84,7 @@ class DefaultKeyBuilder(KeyBuilder):
 
 class RedisStorage(BaseStorage):
     """
-    Redis storage required :code:`aioredis` package installed (:code:`pip install aioredis`)
+    Redis storage required :code:`redis` package installed (:code:`pip install redis`)
     """
 
     def __init__(
@@ -116,7 +116,7 @@ class RedisStorage(BaseStorage):
         Create an instance of :class:`RedisStorage` with specifying the connection string
 
         :param url: for example :code:`redis://user:password@host:port/db`
-        :param connection_kwargs: see :code:`aioredis` docs
+        :param connection_kwargs: see :code:`redis` docs
         :param kwargs: arguments to be passed to :class:`RedisStorage`
         :return: an instance of :class:`RedisStorage`
         """
diff --git a/aiogram/types/user.py b/aiogram/types/user.py
index 64eb5c73..f9e8af24 100644
--- a/aiogram/types/user.py
+++ b/aiogram/types/user.py
@@ -2,13 +2,14 @@ from __future__ import annotations
 
 from typing import Optional
 
+from ..utils.link import create_tg_link
+from ..utils import markdown
 from .base import TelegramObject
 
 
 class User(TelegramObject):
     """
     This object represents a Telegram user or bot.
-
     Source: https://core.telegram.org/bots/api#user
     """
 
@@ -40,3 +41,17 @@ class User(TelegramObject):
         if self.last_name:
             return f"{self.first_name} {self.last_name}"
         return self.first_name
+
+    @property
+    def url(self) -> str:
+        return create_tg_link("user", id=self.id)
+
+    def mention_markdown(self, name: Optional[str] = None) -> str:
+        if name is None:
+            name = self.full_name
+        return markdown.link(name, self.url)
+
+    def mention_html(self, name: Optional[str] = None) -> str:
+        if name is None:
+            name = self.full_name
+        return markdown.hlink(name, self.url)


Test patch:
diff --git a/tests/test_api/test_types/test_user.py b/tests/test_api/test_types/test_user.py
index bda3f94e..c57c0704 100644
--- a/tests/test_api/test_types/test_user.py
+++ b/tests/test_api/test_types/test_user.py
@@ -18,3 +18,35 @@ class TestUser:
     def test_full_name(self, first: str, last: str, result: bool):
         user = User(id=42, is_bot=False, first_name=first, last_name=last)
         assert user.full_name == result
+
+    @pytest.mark.parametrize(
+        "first,last,name",
+        [
+            ["User", None, "bebra"],
+            ["", None, "telegram"],
+            [" ", None, "queue🤬"],
+            ["User", "Name", "Alex"],
+            ["User", " ", "aslo "],
+            [" ", " ", "telebot"],
+        ],
+    )
+    def test_get_mention_markdown(self, first: str, last: str, name: str):
+        user = User(id=42, is_bot=False, first_name=first, last_name=last)
+        assert user.mention_markdown() == f"[{user.full_name}](tg://user?id=42)"
+        assert user.mention_markdown(name=name) == f"[{name}](tg://user?id=42)"
+
+    @pytest.mark.parametrize(
+        "first,last,name",
+        [
+            ["User", None, "bebra"],
+            ["", None, "telegram"],
+            [" ", None, "queue🤬"],
+            ["User", "Name", "Alex"],
+            ["User", " ", "aslo "],
+            [" ", " ", "telebot"],
+        ],
+    )
+    def test_get_mention_html(self, first: str, last: str, name: str):
+        user = User(id=42, is_bot=False, first_name=first, last_name=last)
+        assert user.mention_html() == f'<a href="tg://user?id=42">{user.full_name}</a>'
+        assert user.mention_html(name=name) == f'<a href="tg://user?id=42">{name}</a>'