Skip to content

Commit 009a139

Browse files
Merge pull request #124 from python-discord/invite-regex
2 parents db0ff48 + e96d063 commit 009a139

File tree

4 files changed

+50
-31
lines changed

4 files changed

+50
-31
lines changed

botcore/utils/regex.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
import re
44

55
DISCORD_INVITE = re.compile(
6+
r"(https?://)?(www\.)?" # Optional http(s) and www.
67
r"(discord([.,]|dot)gg|" # Could be discord.gg/
78
r"discord([.,]|dot)com(/|slash)invite|" # or discord.com/invite/
89
r"discordapp([.,]|dot)com(/|slash)invite|" # or discordapp.com/invite/
910
r"discord([.,]|dot)me|" # or discord.me
1011
r"discord([.,]|dot)li|" # or discord.li
1112
r"discord([.,]|dot)io|" # or discord.io.
1213
r"((?<!\w)([.,]|dot))gg" # or .gg/
13-
r")([/]|slash)" # / or 'slash'
14+
r")(/|slash)" # / or 'slash'
1415
r"(?P<invite>\S+)", # the invite code itself
1516
flags=re.IGNORECASE
1617
)
@@ -32,7 +33,7 @@
3233
r"(?P<code>.*?)" # extract all code inside the markup
3334
r"\s*" # any more whitespace before the end of the code markup
3435
r"(?P=delim)", # match the exact same delimiter from the start again
35-
re.DOTALL | re.IGNORECASE # "." also matches newlines, case insensitive
36+
flags=re.DOTALL | re.IGNORECASE # "." also matches newlines, case insensitive
3637
)
3738
"""
3839
Regex for formatted code, using Discord's code blocks.
@@ -44,7 +45,7 @@
4445
r"^(?:[ \t]*\n)*" # any blank (empty or tabs/spaces only) lines before the code
4546
r"(?P<code>.*?)" # extract all the rest as code
4647
r"\s*$", # any trailing whitespace until the end of the string
47-
re.DOTALL # "." also matches newlines
48+
flags=re.DOTALL # "." also matches newlines
4849
)
4950
"""
5051
Regex for raw code, *not* using Discord's code blocks.

docs/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
44
Changelog
55
=========
6+
- :release:`8.1.0 <16th August 2022>`
7+
- :support:`124` Updated :obj:`botcore.utils.regex.DISCORD_INVITE` regex to optionally match leading "http[s]" and "www".
8+
69

710
- :release:`8.0.0 <27th July 2022>`
811
- :breaking:`110` Bump async-rediscache to v1.0.0-rc2

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "bot-core"
3-
version = "8.0.0"
3+
version = "8.1.0"
44
description = "Bot-Core provides the core functionality and utilities for the bots of the Python Discord community."
55
authors = ["Python Discord <info@pythondiscord.com>"]
66
license = "MIT"

tests/botcore/utils/test_regex.py

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,18 @@
44
from botcore.utils.regex import DISCORD_INVITE
55

66

7-
def use_regex(s: str) -> Optional[str]:
8-
"""Helper function to run the Regex on a string.
7+
def match_regex(s: str) -> Optional[str]:
8+
"""Helper function to run re.match on a string.
9+
10+
Return the invite capture group, if the string matches the pattern
11+
else return None
12+
"""
13+
result = DISCORD_INVITE.match(s)
14+
return result if result is None else result.group("invite")
15+
16+
17+
def search_regex(s: str) -> Optional[str]:
18+
"""Helper function to run re.search on a string.
919
1020
Return the invite capture group, if the string matches the pattern
1121
else return None
@@ -19,32 +29,37 @@ class UtilsRegexTests(unittest.TestCase):
1929
def test_discord_invite_positives(self):
2030
"""Test the DISCORD_INVITE regex on a set of strings we would expect to capture."""
2131

22-
self.assertEqual(use_regex("discord.gg/python"), "python")
23-
self.assertEqual(use_regex("https://discord.gg/python"), "python")
24-
self.assertEqual(use_regex("discord.com/invite/python"), "python")
25-
self.assertEqual(use_regex("discordapp.com/invite/python"), "python")
26-
self.assertEqual(use_regex("discord.me/python"), "python")
27-
self.assertEqual(use_regex("discord.li/python"), "python")
28-
self.assertEqual(use_regex("discord.io/python"), "python")
29-
self.assertEqual(use_regex(".gg/python"), "python")
30-
31-
self.assertEqual(use_regex("discord.gg/python/but/extra"), "python/but/extra")
32-
self.assertEqual(use_regex("discord.me/this/isnt/python"), "this/isnt/python")
33-
self.assertEqual(use_regex(".gg/a/a/a/a/a/a/a/a/a/a/a"), "a/a/a/a/a/a/a/a/a/a/a")
34-
self.assertEqual(use_regex("discordapp.com/invite/python/snakescord"), "python/snakescord")
35-
self.assertEqual(use_regex("http://discord.gg/python/%20/notpython"), "python/%20/notpython")
36-
self.assertEqual(use_regex("discord.gg/python?=ts/notpython"), "python?=ts/notpython")
37-
self.assertEqual(use_regex("https://discord.gg/python#fragment/notpython"), "python#fragment/notpython")
38-
self.assertEqual(use_regex("https://discord.gg/python/~/notpython"), "python/~/notpython")
39-
40-
self.assertEqual(use_regex("https://discord.gg/python with whitespace"), "python")
41-
self.assertEqual(use_regex(" https://discord.gg/python "), "python")
32+
self.assertEqual(match_regex("discord.gg/python"), "python")
33+
self.assertEqual(match_regex("https://discord.gg/python"), "python")
34+
self.assertEqual(match_regex("https://www.discord.gg/python"), "python")
35+
self.assertEqual(match_regex("discord.com/invite/python"), "python")
36+
self.assertEqual(match_regex("www.discord.com/invite/python"), "python")
37+
self.assertEqual(match_regex("discordapp.com/invite/python"), "python")
38+
self.assertEqual(match_regex("discord.me/python"), "python")
39+
self.assertEqual(match_regex("discord.li/python"), "python")
40+
self.assertEqual(match_regex("discord.io/python"), "python")
41+
self.assertEqual(match_regex(".gg/python"), "python")
42+
43+
self.assertEqual(match_regex("discord.gg/python/but/extra"), "python/but/extra")
44+
self.assertEqual(match_regex("discord.me/this/isnt/python"), "this/isnt/python")
45+
self.assertEqual(match_regex(".gg/a/a/a/a/a/a/a/a/a/a/a"), "a/a/a/a/a/a/a/a/a/a/a")
46+
self.assertEqual(match_regex("discordapp.com/invite/python/snakescord"), "python/snakescord")
47+
self.assertEqual(match_regex("http://discord.gg/python/%20/notpython"), "python/%20/notpython")
48+
self.assertEqual(match_regex("discord.gg/python?=ts/notpython"), "python?=ts/notpython")
49+
self.assertEqual(match_regex("https://discord.gg/python#fragment/notpython"), "python#fragment/notpython")
50+
self.assertEqual(match_regex("https://discord.gg/python/~/notpython"), "python/~/notpython")
51+
52+
self.assertEqual(search_regex("https://discord.gg/python with whitespace"), "python")
53+
self.assertEqual(search_regex(" https://discord.gg/python "), "python")
4254

4355
def test_discord_invite_negatives(self):
4456
"""Test the DISCORD_INVITE regex on a set of strings we would expect to not capture."""
4557

46-
self.assertEqual(use_regex("another string"), None)
47-
self.assertEqual(use_regex("https://pythondiscord.com"), None)
48-
self.assertEqual(use_regex("https://discord.com"), None)
49-
self.assertEqual(use_regex("https://discord.gg"), None)
50-
self.assertEqual(use_regex("https://discord.gg/ python"), None)
58+
self.assertEqual(match_regex("another string"), None)
59+
self.assertEqual(match_regex("https://pythondiscord.com"), None)
60+
self.assertEqual(match_regex("https://discord.com"), None)
61+
self.assertEqual(match_regex("https://discord.gg"), None)
62+
self.assertEqual(match_regex("https://discord.gg/ python"), None)
63+
64+
self.assertEqual(search_regex("https://discord.com with whitespace"), None)
65+
self.assertEqual(search_regex(" https://discord.com "), None)

0 commit comments

Comments
 (0)