Public Access
feat(follow): add player search with rate limit (#57)
Find public profiles by name: GET /api/follows/players?q=. Queries under 2 characters find nothing; more than 30 searches per minute get 429. LIKE escaping is shared with the library search.
This commit is contained in:
1 parent
c42526bc16
commit
e11fae8e31
12 files changed
+232
-8
No files matched your search
@@ -59,9 +59,10 @@ To Be Played is split into four repositories:
|
||||
Filters --> Out["games + reason"]
|
||||
```
|
||||
- **Follow users (#27)**: a logged-in user follows people with a public profile by display name (`/api/follows`, at most
|
||||
500, never an id in an answer) and gets one inbox note per followed user and batch (`/api/inbox`): a sync with its
|
||||
achievement run, or the hand changes of a quiet 10 minutes. A note counts new games, achievement unlocks, status
|
||||
changes and Steam wishlist adds, and leaves out what the followed user's profile hides (`public_user.sections`).
|
||||
500, never an id in an answer; `GET /api/follows/players?q=` finds public profiles by name, rate-limited) and gets
|
||||
one inbox note per followed user and batch (`/api/inbox`): a sync with its achievement run, or the hand changes of a
|
||||
quiet 10 minutes. A note counts new games, achievement unlocks, status changes and Steam wishlist adds, and leaves
|
||||
out what the followed user's profile hides (`public_user.sections`).
|
||||
Follows end for good, with a note, when the followed user goes private, and without a note when the user is blocked or
|
||||
deleted. Each note keeps one copy of the lines behind its counts (`inbox_note_detail`: games, achievement or trophy
|
||||
names, status moves collapsed per game, wishlist adds; at most 20 achievements per game, the newest unlocks stand for
|
||||
@@ -308,6 +309,7 @@ ArchUnit role rules (`RoleAnnotationRules`) and `src/test/resources/contract/aut
|
||||
| `GET` | `/api/follows` (`{following: [{id, displayName, lastActivityAt}], followers: [{id, displayName, lastActivityAt}]}`, `id` is the follow row; a follower with a private profile has `displayName` null; `lastActivityAt` = the newest digest note the caller got about that person, null for followers and without a note) | login |
|
||||
| `PUT`, `DELETE` | `/api/follows/by-name/{displayName}` (follow, unfollow; `204`; PUT: `404 PROFILE_NOT_FOUND` for an unknown, private, blocked or deleted name, `400 FOLLOW_SELF`, `400 FOLLOW_LIMIT`) | login |
|
||||
| `DELETE` | `/api/follows/{id}` (unfollow, or remove a follower; only rows of the caller change; `204`) | login |
|
||||
| `GET` | `/api/follows/players?q=` (`{results: [{displayName}]}`: public profiles whose name contains `q`, case-insensitive, not blocked or deleted, at most 20, names that start with `q` first, the caller's own name included; `q` under 2 characters answers `[]`; `429 TOO_MANY_SEARCHES` beyond 30 searches per user and minute, `app.follow.search-per-minute`) | login |
|
||||
| `GET` | `/api/inbox` (`{results: [{id, kind, displayName, profileName, newGames, achievements, statusChanges, wishlistAdds, createdAt, read, details}], unread}`, newest 50, `kind` `DIGEST` or `VISIBILITY`) | login |
|
||||
| `GET` | `/api/inbox/{id}/details` (`{results: [{appid, kind, gameName, itemName, fromStatus, toStatus}]}`, `kind` `NEW_GAME`, `ACHIEVEMENT`, `STATUS` or `WISHLIST`; `404` for a note that is not the caller's or not open any more) | login |
|
||||
| `PUT` | `/api/inbox/read` (marks all read; `204`) | login |
|
||||
|
||||
Reference in new issue
Block a user