Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ptbcontrib/extract_urls/README.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind also changing the List to list in the extracturls.py file? If I saw correctly that should make it compatible with py3.10+

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — both return annotations now use built-in list[str], and the local-variable annotation uses dict. I kept compatibility with the existing Python 3.8 CI matrix via postponed annotations; focused tests and all local pre-commit hooks pass.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Please see the docstrings for more details.

## Requirements

* `python-telegram-bot>=12.0`
* `python-telegram-bot~=20.0`

## Authors

Expand Down
9 changes: 5 additions & 4 deletions ptbcontrib/extract_urls/extracturls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains helper functions to extract URLs from messages."""
from __future__ import annotations

import re
from typing import Dict, List

from telegram import Message, MessageEntity


def extract_urls(message: Message) -> List[str]:
def extract_urls(message: Message) -> list[str]:
"""
Extracts all hyperlinks that are contained in a message. This includes message entities and the
media caption, i.e. while of course only text *or* caption is present this works for both.
Expand All @@ -50,7 +51,7 @@ def extract_urls(message: Message) -> List[str]:
results[key] = key.url

# Remove exact duplicates and keep the first appearance
filtered_results: Dict[str, MessageEntity] = {}
filtered_results: dict[str, MessageEntity] = {}
for key, value in results.items():
if not filtered_results.get(value):
filtered_results[value] = key
Expand All @@ -66,7 +67,7 @@ def extract_urls(message: Message) -> List[str]:

def extract_message_links(
message: Message, private_only: bool = False, public_only: bool = False
) -> List[str]:
) -> list[str]:
"""
Extracts all message links that are contained in a message. This includes message entities and
the media caption, i.e. while of course only text *or* caption is present this works for both.
Expand Down
2 changes: 1 addition & 1 deletion ptbcontrib/extract_urls/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
python-telegram-bot>=12.0
python-telegram-bot~=20.0
58 changes: 28 additions & 30 deletions ptbcontrib/longbotcommand/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,54 @@ Provides a `LongBotCommand` class that allows you to store a second, longer desc
Example:

```python
from typing import List

from telegram import Update
from telegram.ext import Updater, CommandHandler, CallbackContext
from ptbcontrib.longbotcommand import LongBotCommand

updater = Updater("TOKEN", use_context=True)
dp = updater.dispatcher
from telegram.ext import Application, CommandHandler, ContextTypes

lorem_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor "
"incididunt ut labore et dolore magna aliqua."
from ptbcontrib.longbotcommand import LongBotCommand

lorem_desc = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. "
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an "
"unknown printer took a galley of type and scrambled it to make a type specimen book. "
"It has survived not only five centuries, but also the leap into electronic typesetting, "
"remaining essentially unchanged."
details_text = "This bot shows how to attach a longer help description to a command."
details_desc = (
"Show the details of this example bot. The longer description appears in /help, while the "
"short description is sent to Telegram's command menu."
)

BOT_COMMANDS: List[LongBotCommand] = [
BOT_COMMANDS = [
LongBotCommand("help", "Prints out a list of available commands"),
LongBotCommand(
"lorem",
"Prints Lorem Ipsum",
long_description = lorem_desc,
"details",
"Show bot details",
long_description=details_desc,
),
]

def help(update: Update, context: CallbackContext) -> None:
for command in context.bot.commands:
# This will only work if you already used set_my_commands!
update.message.reply_text(f"/{command.command}\n\n{command.long_description}")

def lorem(update: Update, context: CallbackContext) -> None:
update.message.reply_text(lorem_text)
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
commands = await context.bot.get_my_commands()
descriptions = {command.command: command.long_description for command in BOT_COMMANDS}
await update.effective_message.reply_text(
"\n\n".join(f"/{command.command}\n\n{descriptions[command.command]}" for command in commands)
)


async def details(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_message.reply_text(details_text)


dp.add_handler(CommandHandler("help", help))
dp.add_handler(CommandHandler("lorem", lorem))
async def post_init(application: Application) -> None:
await application.bot.set_my_commands(BOT_COMMANDS)

dp.bot.set_my_commands(BOT_COMMANDS)

updater.start_polling()
application = Application.builder().token("TOKEN").post_init(post_init).build()
application.add_handler(CommandHandler("help", help_command))
application.add_handler(CommandHandler("details", details))

updater.idle()
application.run_polling()

```

## Requirements

* `20>python-telegram-bot>=13.0`
* `python-telegram-bot~=20.0`

## Authors

Expand Down
2 changes: 1 addition & 1 deletion ptbcontrib/longbotcommand/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
python-telegram-bot>=13.0,<20
python-telegram-bot~=20.0
25 changes: 25 additions & 0 deletions tests/test_extract_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
import pytest
from telegram import Message, MessageEntity
from telegram.constants import MessageEntityType

from ptbcontrib import extract_urls

Expand Down Expand Up @@ -65,6 +66,30 @@ def test_extract_urls_caption(self):
assert test_entities[0]["url"] == results[0]
assert test_entities[2]["url"] == results[1]

def test_extract_urls_entity_type_constants(self):
test_entities = [
{
"length": 6,
"offset": 0,
"type": MessageEntityType.TEXT_LINK,
"url": "http://github.com",
},
{"length": 17, "offset": 23, "type": MessageEntityType.URL},
]
test_message = Message(
message_id=1,
from_user=None,
date=None,
chat=None,
text="Github can be found at http://google.com.",
entities=[MessageEntity(**entity) for entity in test_entities],
)

assert extract_urls.extract_urls(test_message) == [
"http://github.com",
"http://google.com",
]

def test_extract_urls_order(self):
test_entities = [
{"length": 6, "offset": 0, "type": "text_link", "url": "http://github.com"},
Expand Down
14 changes: 9 additions & 5 deletions tests/test_longbotcommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,16 @@ def test_long_desc_init(self, long_desc_command):
assert long_desc_command.description == "desc"
assert long_desc_command.long_description == "long desc"

def test_short_desc_change(self, short_desc_command):
short_desc_command.description = "new desc"
assert short_desc_command.long_description == "new desc"
def test_short_desc_immutable(self, short_desc_command):
with pytest.raises(AttributeError):
short_desc_command.description = "new desc"

assert short_desc_command.long_description == "desc"

def test_long_desc_immutable(self, long_desc_command):
with pytest.raises(AttributeError):
long_desc_command.description = "new desc"

def test_long_desc_change(self, long_desc_command):
long_desc_command.description = "new desc"
assert long_desc_command.long_description == "long desc"

def test_short_desc_dict(self, short_desc_command, bot_command):
Expand Down
Loading