Commit graph

109 commits

Author SHA1 Message Date
3b1926198f Document tests with Given/When/Then comments 2026-08-20 10:51:49 +02:00
fdbf8461cd Point org-social links to git.andros.dev 2026-08-20 10:24:14 +02:00
9c0e825fa1 Add License section to README 2026-08-20 10:02:19 +02:00
2728620fd6 Exclude bridge posts from global and tag-filtered RSS feeds 2026-07-28 10:05:14 +02:00
c446ae514d Exclude bridge virtual feeds from feed listing, discovery and stats
Bridges help users connect to external content (RSS, ActivityPub) but
are not real Org Social accounts. They no longer appear in /feeds/,
cannot be registered via POST, are skipped by both feed discovery
tasks, and do not count in /stats/. A data migration removes bridge
URLs already registered as feeds.
2026-07-20 09:33:28 +02:00
349a5e1376 Add ActivityPub and RSS bridges serving virtual social.org feeds
Expose external accounts as virtual Org Social feeds that any client
can follow with a plain #+FOLLOW: line:

- /bridge/activitypub/@{user}@{instance}/ bridges a Mastodon or any
  ActivityPub account (WebFinger, actor and paginated outbox; only
  public top-level notes, with CW, hashtags, language and attachments)
- /bridge/rss/?url={feed} bridges any RSS/Atom feed (entry title as
  *** sub-heading, converted body and link to the original article)

Registration is implicit on first GET. Bridged data is stored in the
existing Profile/Post tables so /profile/, /search/ and the rest of
the API work on bridged feeds. Active bridges are refreshed every 15
minutes; bridges unrequested for 90 days are cleaned up.

Remote HTML is converted to Org text, escaping headline-like lines so
external content cannot inject posts. Fetches enforce the Webmention
SSRF protections, a 10s timeout and a 5MB size cap. Bridged posts
never queue Webmentions nor publish notifications.
2026-07-17 15:26:41 +02:00
22271f2e0d Send Webmentions for external links found in posts
Implements the sender side of https://www.w3.org/TR/webmention/. During
feed scans, external URLs found in new posts (and links added by edits)
are queued as OutgoingWebmention rows; a periodic task discovers each
target's endpoint and delivers the notification. The unique
(source, target) pair guarantees a webmention is sent at most once, no
matter how many times a feed is rescanned. Targets without an endpoint
are marked permanently, failures retry with exponential backoff, and
endpoints resolving to loopback/private addresses are rejected.
Receiving webmentions is out of scope: plain text feeds cannot
advertise an endpoint.
2026-07-16 10:22:47 +02:00
f7f85153f6 Add /stats/ endpoint with monthly activity and global counters 2026-07-10 08:19:10 +02:00
25b19b948f Replace Django healthcheck with lightweight HTTP probe
manage.py check booted a full Django interpreter every 30s (~1.5s CPU
per run) and never verified the server was actually responding. Probe
the HTTP endpoint directly instead and relax the interval.
2026-07-04 19:39:30 +02:00
97ef297efe Harden feed scanning against bad birthdays and slow hosts
- Drop malformed #+BIRTHDAY values (not YYYY-MM-DD) instead of letting
  them reach the Profile DateField and abort the whole feed scan
- Use a (connect, read) timeout of (3.05, 5) when fetching feeds so dead
  hosts are dropped faster without penalizing slow-but-alive servers
- Add parser and scan_feeds regression tests
2026-06-24 09:17:21 +02:00
045e647ed2 Rewrite SSE view as async using redis.asyncio, fix nginx buffering
Sync generators blocked uvicorn's event loop preventing chunks from
being flushed. Converts to async generators with redis.asyncio so
streaming works correctly under ASGI. Adds /sse/ nginx location with
proxy_buffering off and 1h read timeout.
2026-05-19 09:18:36 +02:00
ee44472c74 Replace Django dev server with uvicorn ASGI
Switches from runserver to uvicorn for proper ASGI support, needed for
SSE streaming responses. Runs with 4 workers on port 8000.
2026-05-19 09:09:16 +02:00
0a66cfcf7a Make ?feed optional in /sse/notifications/, add global stream
Without ?feed=, the endpoint subscribes to all notification channels via
Redis psubscribe("notifications:*") and adds target_feed to each event.
With ?feed=, behavior is unchanged. Updates README and root _links.
2026-05-19 09:06:44 +02:00
347369868d Add /profile/ endpoint returning feed followers
New GET /profile/?feed={url} endpoint that returns the list of feed URLs
that follow the given profile, using the existing Follow model.
Includes cache support, 400/404 error handling, and 8 unit tests.
2026-05-16 11:58:45 +02:00
8b35862bb9 Fix cache backend race that left huey using DummyCache after restart
The previous startup probe ran a 1s TCP connect to Redis at module import
time and silently fell back to DummyCache when it failed. In docker compose
the huey container could finish importing settings.py just before Redis
finished warming up, locking the daemon to DummyCache for its entire lifetime
and breaking cache.delete/cache.clear inside scan_feeds.

Drop the probe; in DEBUG use DummyCache, otherwise always RedisCache.
2026-05-07 09:13:28 +02:00
5a6e953786 Update Contributing section with contribution guidelines link 2026-02-23 09:58:13 +01:00
Andros Fenollosa
109bb2f51c
Fix link formatting in CONTRIBUTING.md 2026-01-19 15:48:44 +01:00
Andros Fenollosa
c7edc34f7f
Create CONTRIBUTING.md 2026-01-19 15:48:32 +01:00
a47aa3ad35 Update 2026-01-19 14:59:42 +01:00
338a8b3121 Simplify diagram labels: use 'Relay' instead of 'Node'
Changed node labels from 'Node X (relay-list.txt)' to simply 'Relay X'
for cleaner visualization. Also updated Concepts section to use 'Relay'
terminology consistently throughout the documentation.
2026-01-19 14:58:52 +01:00
5483f1b7a4 Update diagram: remove centralized 'List nodes'
The relay list is now decentralized - each node maintains its own
local relay-list.txt file. Nodes share feeds directly with each other
in a P2P fashion, without needing a centralized list endpoint.

Changes:
- Remove 'List nodes' from mermaid diagram
- Add relay-list.txt notation to each node
- Update 'Share Users' to 'Share Feeds' for accuracy
- Simplify Concepts section to reflect decentralized architecture
2026-01-19 14:57:19 +01:00
17fe6a9fca Update README: relay list is now in this repository
The relay-list.txt file is now part of this repository, so the
instructions for making a relay public have been updated to reflect
that users should make PRs to this repo instead of the external
org-social repository.

When PRs are merged, all relay nodes that update their code will
automatically get the updated relay list.
2026-01-19 14:55:27 +01:00
13d80cfa0f Isolate list 2026-01-19 14:50:13 +01:00
9a18e3e958 Add comprehensive tests for feed redirect handling
Added test coverage for:
- Basic 301 redirect detection and parsing
- Feed validation with redirects
- Feed URL updates when only old URL exists
- Feed merging when both old and new URLs exist
- Mention migration without UNIQUE constraint errors

The mention migration test specifically validates the fix for the
production bug where feeds with 301 redirects were failing due to
duplicate (post, mentioned_profile) combinations.

All 23 parser tests pass successfully.
2026-01-15 11:47:42 +01:00
1d9a02c304 Fix feed redirect handling for mentions with unique constraints
The feed redirect merge logic was attempting a bulk update of mentions,
which failed when duplicate (post, mentioned_profile) combinations existed.
This caused feeds with 301 redirects to fail merging properly.

Now mentions are migrated individually, checking for existing duplicates
before updating, similar to how Follow and PollVote relationships are handled.

This fixes the UNIQUE constraint errors seen in production for feeds like:
- thesolarprincess.github.io -> thesolarprincess.site
- haiverin.scot -> www.haiverin.scot
- teoten.com -> www.teoten.com
2026-01-15 11:46:26 +01:00
4bf0d8c1d0 Remove CLAUDE.MD from git (should be local only) 2026-01-05 13:56:59 +01:00
b13cf2fad4 Add support for Org Social v1.6
New features from Org Social v1.6:
- Add LOCATION, BIRTHDAY, LANGUAGE, PINNED fields to Profile model
- Support post ID in header (** 2025-05-01T12:00:00+0100)
- Header ID takes priority over property drawer ID
- Parse and store all new v1.6 metadata fields

Changes:
- Updated Profile model with 4 new fields
- Updated parser to extract new metadata fields
- Updated parser to support ID in post headers
- Updated tasks.py to save new profile fields
- Added database migration 0010
- Added 3 new tests for v1.6 features
- Renamed SKILL.md to CLAUDE.MD

All tests passing (58/58)
2026-01-05 13:55:56 +01:00
dc4813c5fc Fix RSS feed chronological order
Parse post_id timestamp for created_at instead of using database insertion time
2025-12-25 11:10:06 +01:00
Andros Fenollosa
94d856a704 Detect and remove deleted posts during feed scanning 2025-12-11 17:04:05 +01:00
Andros Fenollosa
8ca15ffab9 Fix SSE heartbeat blocking issue
The SSE endpoint was using pubsub.listen() which blocks indefinitely
waiting for messages. This prevented heartbeats from being sent when
there was no activity, causing connections to timeout and close.

Changed to use pubsub.get_message(timeout=1) in a while loop, which
allows heartbeats to be sent every 30 seconds even when there are no
new notifications, keeping connections alive.

This fixes the issue where SSE connections would break and users
wouldn't receive real-time notifications.
2025-12-11 16:41:25 +01:00
Andros Fenollosa
9ccd326bea Realtime notification had been added 2025-12-05 09:13:52 +01:00
Andros Fenollosa
7c60f060c8 Added feed content 2025-11-30 17:03:53 +01:00
Andros Fenollosa
75460aa567 fix: Handle Follow relationship constraints during redirect merge
When merging duplicate feeds with redirects, Follow relationships
can generate UNIQUE constraint errors if the relationship already
exists between the same profiles.

This fix:
- Iterates Follow relationships individually
- Checks for existing relationships before updating
- Deletes duplicates safely
- Adds comprehensive error handling

Similar approach to PollVote fix.

Resolves issue with feeds like haiverin.scot redirect.

Signed-off-by: Andros Fenollosa <hi@andros.dev>
2025-11-23 10:58:04 +01:00
Andros Fenollosa
b8c3d98b5d Fixed redirects 2025-11-23 10:53:31 +01:00
Andros Fenollosa
0300a728d2 Refactor 2025-11-17 08:14:26 +01:00
Andros Fenollosa
0873f18c00 Added interactions 2025-11-17 08:07:07 +01:00
Andros Fenollosa
aa5f200fb5 Added boosts 2025-11-16 18:41:45 +01:00
Andros Fenollosa
f09863d6a9 RSS: Added cache system 2025-11-16 09:42:06 +01:00
Andros Fenollosa
84ae9dffcc Posts with empty content was being ignored when fetching RSS feeds. 2025-11-16 09:28:50 +01:00
Andros Fenollosa
fd26468843 Fixed headers 2025-11-16 09:15:50 +01:00
Andros Fenollosa
cc3a270d76 Removed limit 2025-11-15 10:19:28 +01:00
Andros Fenollosa
79ff3a63a5 Added RSS feature 2025-11-15 10:12:46 +01:00
Andros Fenollosa
2f6c7f302c New encoder 2025-11-13 18:20:22 +01:00
Andros Fenollosa
5df132349c Added render 2025-11-13 17:36:55 +01:00
Andros Fenollosa
2491ff9f2a Fix: encode Emoji 2025-11-13 17:31:59 +01:00
Andros Fenollosa
7128200dd8 Middleware cache had been added 2025-11-05 15:27:04 +01:00
Andros Fenollosa
2e3bc8328b Update instructions had been added 2025-11-05 15:17:23 +01:00
Andros Fenollosa
551651afd9 Added etag and mod header 2025-11-05 15:03:20 +01:00
Andros Fenollosa
d2014085f0 Fix parent 2025-11-05 09:37:07 +01:00
Andros Fenollosa
7e0cb6330b Added https://github.com/tanrax/org-social-relay/issues/3 2025-11-05 09:05:50 +01:00