|
1 | 1 | import asyncio |
2 | 2 | import logging |
3 | 3 | import random |
| 4 | +import re |
4 | 5 | import time |
5 | 6 | from collections import deque |
6 | 7 | from copy import deepcopy |
@@ -522,3 +523,50 @@ async def compat_warning(update: Update, _: ContextTypes.DEFAULT_TYPE) -> None: |
522 | 523 | hint.html_markup(), |
523 | 524 | reply_markup=hint.inline_keyboard, |
524 | 525 | ) |
| 526 | + |
| 527 | + |
| 528 | +async def long_code_handling(update: Update, _: ContextTypes.DEFAULT_TYPE) -> None: |
| 529 | + """When someone posts a long code snippet: |
| 530 | + Reply with the /pastebin taghint. |
| 531 | + Because we do the regexing in here rather than in the filter, the corresponding handler |
| 532 | + will have to be in a lower group. |
| 533 | + """ |
| 534 | + message = cast(Message, update.effective_message) |
| 535 | + text = cast(str, message.text) |
| 536 | + has_long_code = False |
| 537 | + |
| 538 | + # We make some educated guesses about the message's content. This is nothing more than |
| 539 | + # a few simple heuristics, but it should catch the most common cases. |
| 540 | + # If we have a code block longer than 15 lines, we assume it's a long code snippet |
| 541 | + parsed_entities = message.parse_entities(types=[MessageEntity.CODE, MessageEntity.PRE]) |
| 542 | + if any(len(text.split("\n")) >= 15 for text in parsed_entities.values()): |
| 543 | + has_long_code = True |
| 544 | + |
| 545 | + # if the text contains more than 5 import lines, we assume it's a long code snippet |
| 546 | + # regex from https://stackoverflow.com/a/44988666/10606962 |
| 547 | + pattern = re.compile(r"(?m)^(?:from +(\S+) +)?import +(\S+)(?: +as +\S+)? *$") |
| 548 | + if not has_long_code and len(pattern.findall(text)) >= 5: |
| 549 | + has_long_code = True |
| 550 | + |
| 551 | + # if the text contains more than 3 class or function definitions, ... |
| 552 | + pattern = re.compile(r"(class|def) [a-zA-Z]+[a-zA-Z0-9_]*\(") |
| 553 | + if not has_long_code and len(pattern.findall(text)) >= 3: |
| 554 | + has_long_code = True |
| 555 | + |
| 556 | + if not has_long_code: |
| 557 | + return |
| 558 | + |
| 559 | + # Get the long_code hint |
| 560 | + hint = TAG_HINTS["pastebin"] |
| 561 | + |
| 562 | + # the leading ". " is important here since html_markup() splits on whitespaces! |
| 563 | + mention = f". {update.effective_user.mention_html()}" if update.effective_user else None |
| 564 | + |
| 565 | + await message.reply_text( |
| 566 | + hint.html_markup(mention), |
| 567 | + reply_markup=hint.inline_keyboard, |
| 568 | + ) |
| 569 | + await try_to_delete(message) |
| 570 | + |
| 571 | + # We don't want this message to be processed any further |
| 572 | + raise ApplicationHandlerStop |
0 commit comments