Skip to content

Commit 9f585f7

Browse files
egeakmanclytaemnestrapre-commit-ci[bot]
authored
Add Bluesky to supported socials (#118)
* Add Bluesky to supported socials * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Mia <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent f5faa5b commit 9f585f7

File tree

7 files changed

+102
-7
lines changed

7 files changed

+102
-7
lines changed

data/examples/europython/speakers.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"homepage": null,
1111
"gitx": "https://github.com/F3DC8A",
1212
"linkedin_url": "https://www.linkedin.com/in/F3DC8A",
13+
"bluesky_url": "https://bsky.app/profile/username.bsky.social",
1314
"mastodon_url": null,
1415
"twitter_url": null,
1516
"website_url": "https://ep2024.europython.eu/speaker/a-speaker"

data/examples/pretalx/speakers.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@
8989
"review": null,
9090
"person": "F3DC8A",
9191
"options": []
92+
},
93+
{
94+
"id": 272249,
95+
"question": {
96+
"id": 3416,
97+
"question": {
98+
"en": "Social (Bluesky)"
99+
}
100+
},
101+
"answer": "username",
102+
"answer_file": null,
103+
"submission": null,
104+
"review": null,
105+
"person": "F3DC8A",
106+
"options": []
92107
},
93108
{
94109
"id": 272249,

src/download.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
pbar.close()
6363

64-
# Save the data to a file
64+
# Save the data to a file
6565
filename = f"{resource_name}_latest.json"
6666
filepath = Config.raw_path / filename
6767

src/misc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ class SpeakerQuestion:
55
affiliation = "Company/Organization/Educational Institution"
66
homepage = "Social (Homepage)"
77
twitter = "Social (X/Twitter)"
8-
mastodon = "Social (Mastodon)"
8+
bluesky = "Social (Bluesky)"
99
linkedin = "Social (LinkedIn)"
10+
mastodon = "Social (Mastodon)"
1011
gitx = "Social (GitHub/GitLab)"
1112

1213

src/models/europython.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class EuroPythonSpeaker(BaseModel):
2828
twitter_url: str | None = None
2929
mastodon_url: str | None = None
3030
linkedin_url: str | None = None
31+
bluesky_url: str | None = None
3132
gitx: str | None = None
3233

3334
@computed_field
@@ -58,6 +59,11 @@ def extract_answers(cls, values) -> dict:
5859
answer.answer_text.strip().split()[0]
5960
)
6061

62+
if answer.question_text == SpeakerQuestion.bluesky:
63+
values["bluesky_url"] = cls.extract_bluesky_url(
64+
answer.answer_text.strip().split()[0]
65+
)
66+
6167
if answer.question_text == SpeakerQuestion.linkedin:
6268
values["linkedin_url"] = cls.extract_linkedin_url(
6369
answer.answer_text.strip().split()[0]
@@ -114,6 +120,36 @@ def extract_linkedin_url(text: str) -> str:
114120

115121
return linkedin_url.split("?")[0]
116122

123+
@staticmethod
124+
def extract_bluesky_url(text: str) -> str:
125+
"""
126+
Returns a normalized BlueSky URL in the form https://bsky.app/profile/<USERNAME>.bsky.social,
127+
or uses the entire domain if it's custom (e.g., .dev).
128+
"""
129+
text = text.split("?", 1)[0].strip()
130+
131+
if text.startswith("https://"):
132+
text = text[8:]
133+
elif text.startswith("http://"):
134+
text = text[7:]
135+
136+
if text.startswith("www."):
137+
text = text[4:]
138+
139+
for marker in ("bsky.app/profile/", "bsky/"):
140+
if marker in text:
141+
text = text.split(marker, 1)[1]
142+
break
143+
# case custom domain
144+
else:
145+
text = text.rsplit("/", 1)[-1]
146+
147+
# if there's no dot, assume it's a non-custom handle and append '.bsky.social'
148+
if "." not in text:
149+
text += ".bsky.social"
150+
151+
return f"https://bsky.app/profile/{text}"
152+
117153

118154
class EuroPythonSession(BaseModel):
119155
"""

src/transform.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
from src.utils.utils import Utils
88

99
if __name__ == "__main__":
10-
parser = ArgumentParser(description="Transform data from Pretalx to EuroPython format and save it.")
10+
parser = ArgumentParser(
11+
description="Transform data from Pretalx to EuroPython format and save it."
12+
)
1113
parser.add_argument(
1214
"-w",
1315
"--warn-dupes",
@@ -24,8 +26,9 @@
2426
args = parser.parse_args()
2527
exclude = set(args.exclude or [])
2628

27-
28-
print(f"Parsing submissions from {Config.raw_path}/submissions_latest.json...", end="")
29+
print(
30+
f"Parsing submissions from {Config.raw_path}/submissions_latest.json...", end=""
31+
)
2932
pretalx_submissions = Parse.publishable_submissions(
3033
Config.raw_path / "submissions_latest.json"
3134
)
@@ -38,7 +41,10 @@
3841
print(" done.")
3942

4043
if "youtube" not in exclude:
41-
print(f"Parsing YouTube data from {Config.raw_path}/youtube_latest.json...", end="")
44+
print(
45+
f"Parsing YouTube data from {Config.raw_path}/youtube_latest.json...",
46+
end="",
47+
)
4248
youtube_data = Parse.youtube(Config.raw_path / "youtube_latest.json")
4349
print(" done.")
4450
else:
@@ -77,7 +83,9 @@
7783
print(" done.")
7884

7985
if "schedule" not in exclude:
80-
print("\nParsing schedule from {Config.raw_path}/schedule_latest.json...", end="")
86+
print(
87+
"\nParsing schedule from {Config.raw_path}/schedule_latest.json...", end=""
88+
)
8189
pretalx_schedule = Parse.schedule(Config.raw_path / "schedule_latest.json")
8290
print(" done.")
8391

tests/test_social_media_extractions.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,37 @@ def test_extract_mastodon_url(input_string: str, result: str) -> None:
3232
)
3333
def test_extract_linkedin_url(input_string: str, result: str) -> None:
3434
assert EuroPythonSpeaker.extract_linkedin_url(input_string) == result
35+
36+
37+
@pytest.mark.parametrize(
38+
("input_string", "result"),
39+
[
40+
("username", "https://bsky.app/profile/username.bsky.social"),
41+
("username.dev", "https://bsky.app/profile/username.dev"),
42+
("username.bsky.social", "https://bsky.app/profile/username.bsky.social"),
43+
("bsky.app/profile/username", "https://bsky.app/profile/username.bsky.social"),
44+
("bsky/username", "https://bsky.app/profile/username.bsky.social"),
45+
(
46+
"www.bsky.app/profile/username",
47+
"https://bsky.app/profile/username.bsky.social",
48+
),
49+
(
50+
"www.bsky.app/profile/username.bsky.social",
51+
"https://bsky.app/profile/username.bsky.social",
52+
),
53+
(
54+
"http://bsky.app/profile/username",
55+
"https://bsky.app/profile/username.bsky.social",
56+
),
57+
(
58+
"https://bsky.app/profile/username.com",
59+
"https://bsky.app/profile/username.com",
60+
),
61+
(
62+
"https://bsky.app/profile/username.bsky.social",
63+
"https://bsky.app/profile/username.bsky.social",
64+
),
65+
],
66+
)
67+
def test_extract_bluesky_url(input_string: str, result: str) -> None:
68+
assert EuroPythonSpeaker.extract_bluesky_url(input_string) == result

0 commit comments

Comments
 (0)