|
59 | 59 | Undefined,
|
60 | 60 | MISSING,
|
61 | 61 | format_dt,
|
| 62 | + escape_mentions, |
| 63 | + raw_mentions, |
| 64 | + raw_channel_mentions, |
| 65 | + raw_mentions, |
| 66 | + remove_markdown, |
| 67 | + escape_markdown, |
62 | 68 | )
|
63 | 69 |
|
64 | 70 | try:
|
@@ -350,187 +356,3 @@ def get(self, element: int) -> int | None:
|
350 | 356 | def has(self, element: int) -> bool:
|
351 | 357 | i = bisect_left(self, element)
|
352 | 358 | return i != len(self) and self[i] == element
|
353 |
| - |
354 |
| - |
355 |
| -_MARKDOWN_ESCAPE_SUBREGEX = "|".join(r"\{0}(?=([\s\S]*((?<!\{0})\{0})))".format(c) for c in ("*", "`", "_", "~", "|")) |
356 |
| - |
357 |
| -# regular expression for finding and escaping links in markdown |
358 |
| -# note: technically, brackets are allowed in link text. |
359 |
| -# perhaps more concerning, parentheses are also allowed in link destination. |
360 |
| -# this regular expression matches neither of those. |
361 |
| -# this page provides a good reference: http://blog.michaelperrin.fr/2019/02/04/advanced-regular-expressions/ |
362 |
| -_MARKDOWN_ESCAPE_LINKS = r""" |
363 |
| -\[ # matches link text |
364 |
| - [^\[\]]* # link text can contain anything but brackets |
365 |
| -\] |
366 |
| -\( # matches link destination |
367 |
| - [^\(\)]+ # link destination cannot contain parentheses |
368 |
| -\)""" # note 2: make sure this regex is consumed in re.X (extended mode) since it has whitespace and comments |
369 |
| - |
370 |
| -_MARKDOWN_ESCAPE_COMMON = rf"^>(?:>>)?\s|{_MARKDOWN_ESCAPE_LINKS}" |
371 |
| - |
372 |
| -_MARKDOWN_ESCAPE_REGEX = re.compile( |
373 |
| - rf"(?P<markdown>{_MARKDOWN_ESCAPE_SUBREGEX}|{_MARKDOWN_ESCAPE_COMMON})", |
374 |
| - re.MULTILINE | re.X, |
375 |
| -) |
376 |
| - |
377 |
| -_URL_REGEX = r"(?P<url><[^: >]+:\/[^ >]+>|(?:https?|steam):\/\/[^\s<]+[^<.,:;\"\'\]\s])" |
378 |
| - |
379 |
| -_MARKDOWN_STOCK_REGEX = rf"(?P<markdown>[_\\~|\*`]|{_MARKDOWN_ESCAPE_COMMON})" |
380 |
| - |
381 |
| - |
382 |
| -def remove_markdown(text: str, *, ignore_links: bool = True) -> str: |
383 |
| - """A helper function that removes markdown characters. |
384 |
| -
|
385 |
| - .. versionadded:: 1.7 |
386 |
| -
|
387 |
| - .. note:: |
388 |
| - This function is not markdown aware and may remove meaning from the original text. For example, |
389 |
| - if the input contains ``10 * 5`` then it will be converted into ``10 5``. |
390 |
| -
|
391 |
| - Parameters |
392 |
| - ---------- |
393 |
| - text: :class:`str` |
394 |
| - The text to remove markdown from. |
395 |
| - ignore_links: :class:`bool` |
396 |
| - Whether to leave links alone when removing markdown. For example, |
397 |
| - if a URL in the text contains characters such as ``_`` then it will |
398 |
| - be left alone. Defaults to ``True``. |
399 |
| -
|
400 |
| - Returns |
401 |
| - ------- |
402 |
| - :class:`str` |
403 |
| - The text with the markdown special characters removed. |
404 |
| - """ |
405 |
| - |
406 |
| - def replacement(match): |
407 |
| - groupdict = match.groupdict() |
408 |
| - return groupdict.get("url", "") |
409 |
| - |
410 |
| - regex = _MARKDOWN_STOCK_REGEX |
411 |
| - if ignore_links: |
412 |
| - regex = f"(?:{_URL_REGEX}|{regex})" |
413 |
| - return re.sub(regex, replacement, text, 0, re.MULTILINE) |
414 |
| - |
415 |
| - |
416 |
| -def escape_markdown(text: str, *, as_needed: bool = False, ignore_links: bool = True) -> str: |
417 |
| - r"""A helper function that escapes Discord's markdown. |
418 |
| -
|
419 |
| - Parameters |
420 |
| - ----------- |
421 |
| - text: :class:`str` |
422 |
| - The text to escape markdown from. |
423 |
| - as_needed: :class:`bool` |
424 |
| - Whether to escape the markdown characters as needed. This |
425 |
| - means that it does not escape extraneous characters if it's |
426 |
| - not necessary, e.g. ``**hello**`` is escaped into ``\*\*hello**`` |
427 |
| - instead of ``\*\*hello\*\*``. Note however that this can open |
428 |
| - you up to some clever syntax abuse. Defaults to ``False``. |
429 |
| - ignore_links: :class:`bool` |
430 |
| - Whether to leave links alone when escaping markdown. For example, |
431 |
| - if a URL in the text contains characters such as ``_`` then it will |
432 |
| - be left alone. This option is not supported with ``as_needed``. |
433 |
| - Defaults to ``True``. |
434 |
| -
|
435 |
| - Returns |
436 |
| - -------- |
437 |
| - :class:`str` |
438 |
| - The text with the markdown special characters escaped with a slash. |
439 |
| - """ |
440 |
| - |
441 |
| - if not as_needed: |
442 |
| - |
443 |
| - def replacement(match): |
444 |
| - groupdict = match.groupdict() |
445 |
| - is_url = groupdict.get("url") |
446 |
| - if is_url: |
447 |
| - return is_url |
448 |
| - return f"\\{groupdict['markdown']}" |
449 |
| - |
450 |
| - regex = _MARKDOWN_STOCK_REGEX |
451 |
| - if ignore_links: |
452 |
| - regex = f"(?:{_URL_REGEX}|{regex})" |
453 |
| - return re.sub(regex, replacement, text, 0, re.MULTILINE | re.X) |
454 |
| - else: |
455 |
| - text = re.sub(r"\\", r"\\\\", text) |
456 |
| - return _MARKDOWN_ESCAPE_REGEX.sub(r"\\\1", text) |
457 |
| - |
458 |
| - |
459 |
| -def escape_mentions(text: str) -> str: |
460 |
| - """A helper function that escapes everyone, here, role, and user mentions. |
461 |
| -
|
462 |
| - .. note:: |
463 |
| -
|
464 |
| - This does not include channel mentions. |
465 |
| -
|
466 |
| - .. note:: |
467 |
| -
|
468 |
| - For more granular control over what mentions should be escaped |
469 |
| - within messages, refer to the :class:`~discord.AllowedMentions` |
470 |
| - class. |
471 |
| -
|
472 |
| - Parameters |
473 |
| - ---------- |
474 |
| - text: :class:`str` |
475 |
| - The text to escape mentions from. |
476 |
| -
|
477 |
| - Returns |
478 |
| - ------- |
479 |
| - :class:`str` |
480 |
| - The text with the mentions removed. |
481 |
| - """ |
482 |
| - return re.sub(r"@(everyone|here|[!&]?[0-9]{17,20})", "@\u200b\\1", text) |
483 |
| - |
484 |
| - |
485 |
| -def raw_mentions(text: str) -> list[int]: |
486 |
| - """Returns a list of user IDs matching ``<@user_id>`` in the string. |
487 |
| -
|
488 |
| - .. versionadded:: 2.2 |
489 |
| -
|
490 |
| - Parameters |
491 |
| - ---------- |
492 |
| - text: :class:`str` |
493 |
| - The string to get user mentions from. |
494 |
| -
|
495 |
| - Returns |
496 |
| - ------- |
497 |
| - List[:class:`int`] |
498 |
| - A list of user IDs found in the string. |
499 |
| - """ |
500 |
| - return [int(x) for x in re.findall(r"<@!?([0-9]+)>", text)] |
501 |
| - |
502 |
| - |
503 |
| -def raw_channel_mentions(text: str) -> list[int]: |
504 |
| - """Returns a list of channel IDs matching ``<@#channel_id>`` in the string. |
505 |
| -
|
506 |
| - .. versionadded:: 2.2 |
507 |
| -
|
508 |
| - Parameters |
509 |
| - ---------- |
510 |
| - text: :class:`str` |
511 |
| - The string to get channel mentions from. |
512 |
| -
|
513 |
| - Returns |
514 |
| - ------- |
515 |
| - List[:class:`int`] |
516 |
| - A list of channel IDs found in the string. |
517 |
| - """ |
518 |
| - return [int(x) for x in re.findall(r"<#([0-9]+)>", text)] |
519 |
| - |
520 |
| - |
521 |
| -def raw_role_mentions(text: str) -> list[int]: |
522 |
| - """Returns a list of role IDs matching ``<@&role_id>`` in the string. |
523 |
| -
|
524 |
| - .. versionadded:: 2.2 |
525 |
| -
|
526 |
| - Parameters |
527 |
| - ---------- |
528 |
| - text: :class:`str` |
529 |
| - The string to get role mentions from. |
530 |
| -
|
531 |
| - Returns |
532 |
| - ------- |
533 |
| - List[:class:`int`] |
534 |
| - A list of role IDs found in the string. |
535 |
| - """ |
536 |
| - return [int(x) for x in re.findall(r"<@&([0-9]+)>", text)] |
0 commit comments