Skip to content
Merged
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
1 change: 1 addition & 0 deletions data/examples/europython/speakers.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"homepage": null,
"gitx": "https://github.com/F3DC8A",
"linkedin_url": "https://www.linkedin.com/in/F3DC8A",
"bluesky_url": "https://bsky.app/profile/username.bsky.social",
"mastodon_url": null,
"twitter_url": null,
"website_url": "https://ep2024.europython.eu/speaker/a-speaker"
Expand Down
15 changes: 15 additions & 0 deletions data/examples/pretalx/speakers.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@
"review": null,
"person": "F3DC8A",
"options": []
},
{
"id": 272249,
"question": {
"id": 3416,
"question": {
"en": "Social (Bluesky)"
}
},
"answer": "username",
"answer_file": null,
"submission": null,
"review": null,
"person": "F3DC8A",
"options": []
},
{
"id": 272249,
Expand Down
2 changes: 1 addition & 1 deletion src/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@

pbar.close()

# Save the data to a file
# Save the data to a file
filename = f"{resource_name}_latest.json"
filepath = Config.raw_path / filename

Expand Down
3 changes: 2 additions & 1 deletion src/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ class SpeakerQuestion:
affiliation = "Company/Organization/Educational Institution"
homepage = "Social (Homepage)"
twitter = "Social (X/Twitter)"
mastodon = "Social (Mastodon)"
bluesky = "Social (Bluesky)"
linkedin = "Social (LinkedIn)"
mastodon = "Social (Mastodon)"
gitx = "Social (GitHub/GitLab)"


Expand Down
36 changes: 36 additions & 0 deletions src/models/europython.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class EuroPythonSpeaker(BaseModel):
twitter_url: str | None = None
mastodon_url: str | None = None
linkedin_url: str | None = None
bluesky_url: str | None = None
gitx: str | None = None

@computed_field
Expand Down Expand Up @@ -58,6 +59,11 @@ def extract_answers(cls, values) -> dict:
answer.answer_text.strip().split()[0]
)

if answer.question_text == SpeakerQuestion.bluesky:
values["bluesky_url"] = cls.extract_bluesky_url(
answer.answer_text.strip().split()[0]
)

if answer.question_text == SpeakerQuestion.linkedin:
values["linkedin_url"] = cls.extract_linkedin_url(
answer.answer_text.strip().split()[0]
Expand Down Expand Up @@ -114,6 +120,36 @@ def extract_linkedin_url(text: str) -> str:

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

@staticmethod
def extract_bluesky_url(text: str) -> str:
"""
Returns a normalized BlueSky URL in the form https://bsky.app/profile/<USERNAME>.bsky.social,
or uses the entire domain if it's custom (e.g., .dev).
"""
text = text.split("?", 1)[0].strip()

if text.startswith("https://"):
text = text[8:]
elif text.startswith("http://"):
text = text[7:]

if text.startswith("www."):
text = text[4:]

for marker in ("bsky.app/profile/", "bsky/"):
if marker in text:
text = text.split(marker, 1)[1]
break
# case custom domain
else:
text = text.rsplit("/", 1)[-1]

# if there's no dot, assume it's a non-custom handle and append '.bsky.social'
if "." not in text:
text += ".bsky.social"

return f"https://bsky.app/profile/{text}"


class EuroPythonSession(BaseModel):
"""
Expand Down
18 changes: 13 additions & 5 deletions src/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
from src.utils.utils import Utils

if __name__ == "__main__":
parser = ArgumentParser(description="Transform data from Pretalx to EuroPython format and save it.")
parser = ArgumentParser(
description="Transform data from Pretalx to EuroPython format and save it."
)
parser.add_argument(
"-w",
"--warn-dupes",
Expand All @@ -24,8 +26,9 @@
args = parser.parse_args()
exclude = set(args.exclude or [])


print(f"Parsing submissions from {Config.raw_path}/submissions_latest.json...", end="")
print(
f"Parsing submissions from {Config.raw_path}/submissions_latest.json...", end=""
)
pretalx_submissions = Parse.publishable_submissions(
Config.raw_path / "submissions_latest.json"
)
Expand All @@ -38,7 +41,10 @@
print(" done.")

if "youtube" not in exclude:
print(f"Parsing YouTube data from {Config.raw_path}/youtube_latest.json...", end="")
print(
f"Parsing YouTube data from {Config.raw_path}/youtube_latest.json...",
end="",
)
youtube_data = Parse.youtube(Config.raw_path / "youtube_latest.json")
print(" done.")
else:
Expand Down Expand Up @@ -77,7 +83,9 @@
print(" done.")

if "schedule" not in exclude:
print("\nParsing schedule from {Config.raw_path}/schedule_latest.json...", end="")
print(
"\nParsing schedule from {Config.raw_path}/schedule_latest.json...", end=""
)
pretalx_schedule = Parse.schedule(Config.raw_path / "schedule_latest.json")
print(" done.")

Expand Down
34 changes: 34 additions & 0 deletions tests/test_social_media_extractions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,37 @@ def test_extract_mastodon_url(input_string: str, result: str) -> None:
)
def test_extract_linkedin_url(input_string: str, result: str) -> None:
assert EuroPythonSpeaker.extract_linkedin_url(input_string) == result


@pytest.mark.parametrize(
("input_string", "result"),
[
("username", "https://bsky.app/profile/username.bsky.social"),
("username.dev", "https://bsky.app/profile/username.dev"),
("username.bsky.social", "https://bsky.app/profile/username.bsky.social"),
("bsky.app/profile/username", "https://bsky.app/profile/username.bsky.social"),
("bsky/username", "https://bsky.app/profile/username.bsky.social"),
(
"www.bsky.app/profile/username",
"https://bsky.app/profile/username.bsky.social",
),
(
"www.bsky.app/profile/username.bsky.social",
"https://bsky.app/profile/username.bsky.social",
),
(
"http://bsky.app/profile/username",
"https://bsky.app/profile/username.bsky.social",
),
(
"https://bsky.app/profile/username.com",
"https://bsky.app/profile/username.com",
),
(
"https://bsky.app/profile/username.bsky.social",
"https://bsky.app/profile/username.bsky.social",
),
],
)
def test_extract_bluesky_url(input_string: str, result: str) -> None:
assert EuroPythonSpeaker.extract_bluesky_url(input_string) == result
Loading