Skip to content

Commit e6b6815

Browse files
authored
Merge branch 'nanos:main' into main
2 parents 536e461 + ca4c0b2 commit e6b6815

File tree

5 files changed

+96
-72
lines changed

5 files changed

+96
-72
lines changed

.github/workflows/get_context.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
cache: 'pip' # caching pip dependencies
2323
- run: pip install -r requirements.txt
2424
- name: Download all workflow run artifacts
25-
uses: dawidd6/action-download-artifact@v3
25+
uses: dawidd6/action-download-artifact@v6
2626
with:
2727
name: artifacts
2828
workflow: get_context.yml
@@ -37,7 +37,8 @@ jobs:
3737
name: artifacts
3838
path: |
3939
artifacts
40-
- name: Checkout user's forked repository for keeping workflow alive
41-
uses: actions/checkout@v4
42-
- name: Keep workflow alive
43-
uses: gautamkrishnar/keepalive-workflow@v1
40+
# Temporarily disable these while we figure out what to do.
41+
# - name: Checkout user's forked repository for keeping workflow alive
42+
# uses: actions/checkout@v4
43+
# - name: Keep workflow alive
44+
# uses: gautamkrishnar/keepalive-workflow@v1

.github/workflows/update-version-number.yaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ jobs:
1818
git config user.email bot@thms.uk
1919
VERSION=${{ github.ref_name }}
2020
VERSION="${VERSION:1}"
21-
sed -i -E 's/VERSION = "[0-9]+.[0-9]+.[0-9]+"/VERSION = "'$VERSION'"/' find_posts.py
22-
git add find_posts.py
23-
git commit -m "[bot] Bump version to $VERSION"
24-
git push origin HEAD:main > /dev/null 2>&1
25-
git tag -f "v$VERSION"
26-
git push -f origin "v$VERSION" > /dev/null 2>&1
21+
if ! grep "VERSION = \"$VERSION\"" "find_posts.py"; then
22+
sed -i -E 's/VERSION = "[0-9]+.[0-9]+.[0-9]+"/VERSION = "'$VERSION'"/' find_posts.py
23+
git add find_posts.py
24+
git commit -m "[bot] Bump version to $VERSION"
25+
git push origin HEAD:main > /dev/null 2>&1
26+
git tag -f "v$VERSION"
27+
git push -f origin "v$VERSION" > /dev/null 2>&1
28+
fi
2729
2830
docker:
2931
runs-on: ubuntu-latest

find_posts.py

Lines changed: 56 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
logger = logging.getLogger("FediFetcher")
2121
robotParser = urllib.robotparser.RobotFileParser()
2222

23-
VERSION = "7.1.12"
23+
VERSION = "7.1.16"
2424

2525
argparser=argparse.ArgumentParser()
2626

@@ -367,19 +367,12 @@ def get_timeline(server, access_token, max):
367367

368368
if response.status_code == 200:
369369
toots = response.json()
370-
elif response.status_code == 401:
371-
raise Exception(
372-
f"Error getting URL {url}. Status code: {response.status_code}. "
373-
"Ensure your access token is correct"
374-
)
375-
elif response.status_code == 403:
376-
raise Exception(
377-
f"Error getting URL {url}. Status code: {response.status_code}. "
378-
"Make sure you have the read:statuses scope enabled for your access token."
379-
)
380370
else:
381-
raise Exception(
382-
f"Error getting URL {url}. Status code: {response.status_code}"
371+
report_mastodon_error(
372+
f"Error getting URL {url}",
373+
response.status_code,
374+
access_token,
375+
"read:statuses"
383376
)
384377

385378
# Paginate as needed
@@ -401,19 +394,12 @@ def get_toots(url, access_token):
401394

402395
if response.status_code == 200:
403396
return response
404-
elif response.status_code == 401:
405-
raise Exception(
406-
f"Error getting URL {url}. Status code: {response.status_code}. "
407-
"It looks like your access token is incorrect."
408-
)
409-
elif response.status_code == 403:
410-
raise Exception(
411-
f"Error getting URL {url}. Status code: {response.status_code}. "
412-
"Make sure you have the read:statuses scope enabled for your access token."
413-
)
414397
else:
415-
raise Exception(
416-
f"Error getting URL {url}. Status code: {response.status_code}"
398+
report_mastodon_error(
399+
f"Error getting URL {url}",
400+
response.status_code,
401+
access_token,
402+
"read:statuses"
417403
)
418404

419405
def get_active_user_ids(server, access_token, reply_interval_hours):
@@ -432,19 +418,12 @@ def get_active_user_ids(server, access_token, reply_interval_hours):
432418
if last_active > since:
433419
logger.info(f"Found active user: {user['username']}")
434420
yield user["id"]
435-
elif resp.status_code == 401:
436-
raise Exception(
437-
f"Error getting user IDs on server {server}. Status code: {resp.status_code}. "
438-
"Ensure your access token is correct"
439-
)
440-
elif resp.status_code == 403:
441-
raise Exception(
442-
f"Error getting user IDs on server {server}. Status code: {resp.status_code}. "
443-
"Make sure you have the admin:read:accounts scope enabled for your access token."
444-
)
445421
else:
446-
raise Exception(
447-
f"Error getting user IDs on server {server}. Status code: {resp.status_code}"
422+
report_mastodon_error(
423+
f"Error getting user IDs on server {server}",
424+
resp.status_code,
425+
access_token,
426+
"admin:read:accounts"
448427
)
449428

450429

@@ -491,16 +470,14 @@ def get_reply_toots(user_id, server, access_token, seen_urls, reply_since):
491470
for toot in toots:
492471
logger.debug(f"Found reply toot: {toot['url']}")
493472
return toots
494-
elif resp.status_code == 403:
495-
raise Exception(
496-
f"Error getting replies for user {user_id} on server {server}. Status code: {resp.status_code}. "
497-
"Make sure you have the read:statuses scope enabled for your access token."
473+
else:
474+
report_mastodon_error(
475+
f"Error getting replies for user {user_id} on server {server}",
476+
resp.status_code,
477+
access_token,
478+
"read:statuses"
498479
)
499480

500-
raise Exception(
501-
f"Error getting replies for user {user_id} on server {server}. Status code: {resp.status_code}"
502-
)
503-
504481

505482
def toot_context_can_be_fetched(toot):
506483
fetchable = toot["visibility"] in ["public", "unlisted"]
@@ -651,6 +628,11 @@ def parse_url(url, parsed_urls):
651628
if match is not None:
652629
parsed_urls[url] = match
653630

631+
if url not in parsed_urls:
632+
match = parse_pleroma_uri(url)
633+
if match is not None:
634+
parsed_urls[url] = match
635+
654636
if url not in parsed_urls:
655637
match = parse_lemmy_url(url)
656638
if match is not None:
@@ -719,6 +701,13 @@ def parse_pleroma_url(url):
719701
return None
720702
return None
721703

704+
def parse_pleroma_uri(uri):
705+
"""parse a Pleroma URL and return the server and ID"""
706+
match = re.match(r"https://(?P<server>[^/]+)/notice/(?P<toot_id>[^/]+)", uri)
707+
if match is not None:
708+
return (match.group("server"), match.group("toot_id"))
709+
return None
710+
722711
def parse_pleroma_profile_url(url):
723712
"""parse a Pleroma Profile URL and return the server and username"""
724713
match = re.match(r"https://(?P<server>[^/]+)/users/(?P<username>[^/]+)", url)
@@ -1033,20 +1022,11 @@ def get_paginated_mastodon(url, max, headers = {}, timeout = 0, max_tries = 5):
10331022
response = get(furl, headers, timeout, max_tries)
10341023

10351024
if response.status_code != 200:
1036-
if response.status_code == 401:
1037-
raise Exception(
1038-
f"Error getting URL {url}. Status code: {response.status_code}. "
1039-
"Ensure your access token is correct"
1040-
)
1041-
elif response.status_code == 403:
1042-
raise Exception(
1043-
f"Error getting URL {url}. Status code: {response.status_code}. "
1044-
"Make sure you have the correct scopes enabled for your access token."
1045-
)
1046-
else:
1047-
raise Exception(
1048-
f"Error getting URL {url}. Status code: {response.status_code}"
1049-
)
1025+
report_mastodon_error(
1026+
f"Error getting URL {url}",
1027+
response.status_code,
1028+
headers.get('Authorization', '').replace("Bearer ", ""),
1029+
)
10501030

10511031
result = response.json()
10521032

@@ -1470,6 +1450,22 @@ def fetch_timeline_context(timeline_posts, token, parsed_urls, seen_hosts, seen_
14701450

14711451
add_user_posts(arguments.server, token, filter_known_users(mentioned_users, all_known_users), recently_checked_users, all_known_users, seen_urls, seen_hosts)
14721452

1453+
def report_mastodon_error(error_message, error_code, access_token, required_scope = ''):
1454+
subline = ""
1455+
match error_code:
1456+
case 401:
1457+
subline = "\nIt looks like your access token is incorrect. Consider generating a new access token, and/or ensure you have copy and pasted the whole token correctly."
1458+
case 403:
1459+
if(required_scope != ""):
1460+
subline = f"\nAdd the {required_scope} scope to your access token, and regenerate the token."
1461+
else:
1462+
subline = "\nMake sure you have enabled the required scope(s) for your token."
1463+
1464+
raise Exception(
1465+
f"{error_message} with token {access_token[:+5]}{'*' * (len(access_token) - 10)}{access_token[-5:]}. Status code: {error_code} "
1466+
f"{subline}"
1467+
)
1468+
14731469
if __name__ == "__main__":
14741470
start = datetime.now()
14751471

@@ -1519,7 +1515,7 @@ def fetch_timeline_context(timeline_posts, token, parsed_urls, seen_hosts, seen_
15191515
if tokens := [token for envvar, token in os.environ.items() if envvar.lower().startswith("ff_access_token")]:
15201516
arguments.access_token = tokens
15211517

1522-
logger.info("Starting FediFetcher")
1518+
logger.info(f"Starting FediFetcher v{VERSION}")
15231519

15241520
if(arguments.server == None or arguments.access_token == None):
15251521
logger.critical("You must supply at least a server name and an access token")

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ packaging==24.1
88
pluggy==1.5.0
99
pytest==8.2.2
1010
python-dateutil==2.8.2
11-
requests==2.32.0
11+
requests==2.32.3
1212
six==1.16.0
1313
smmap==5.0.0
1414
urllib3==1.26.19

tests/test_find_posts.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
parse_pixelfed_profile_url,
4040
parse_pixelfed_url,
4141
parse_pleroma_url,
42+
parse_pleroma_uri,
4243
post,
4344
set_server_apis,
4445
user_has_opted_out,
46+
parse_url
4547
)
4648

4749

@@ -874,6 +876,10 @@ def test_parse_pleroma_url(mock_get_redirect_url):
874876
result = parse_pleroma_url("https://different.example.com/objects/111")
875877
assert result == ("different.example.com", "789")
876878

879+
def test_parse_pleroma_uri():
880+
# Test that a valid URI is correctly parsed
881+
uri = "https://friedcheese.us/notice/Arv4zBVnAR84mmkVay"
882+
assert parse_pleroma_uri(uri) == ("friedcheese.us", "Arv4zBVnAR84mmkVay")
877883

878884
import re
879885
import pytest
@@ -951,6 +957,25 @@ def test_parse_peertube_url_valid():
951957
# assert that the result is as expected
952958
assert result == expected
953959

960+
def test_parse_url():
961+
tests = [
962+
(
963+
"https://video.infosec.exchange/videos/watch/56f1d0b5-d98f-4bad-b1e7-648ae074ab9d",
964+
("video.infosec.exchange", "56f1d0b5-d98f-4bad-b1e7-648ae074ab9d")
965+
),
966+
(
967+
"https://veedeo.org/videos/watch/a51bb77c-e1bd-4d6a-b119-95af176f6d66",
968+
("veedeo.org", "a51bb77c-e1bd-4d6a-b119-95af176f6d66")
969+
),
970+
(
971+
'https://foo.bar/nothing',
972+
None
973+
)
974+
]
975+
for (url,expected) in tests:
976+
result = parse_url(url, {})
977+
assert result == expected
978+
954979

955980
def test_parse_peertube_url_invalid():
956981
# define an invalid url

0 commit comments

Comments
 (0)