forked from retoor/devplacepy
fix: correct "bugs" to "issues" in routing table and README references across multiple documentation files
This commit is contained in:
@@ -25,6 +25,7 @@ Open `http://localhost:10500`.
|
||||
| Database | SQLite via `dataset` (auto-sync schema, `uid` PKs, WAL mode, 30s busy timeout) |
|
||||
| Auth | Session cookie, API key (`X-API-KEY`/Bearer), or HTTP Basic; PBKDF2-SHA256 via passlib |
|
||||
| Avatars | Multiavatar (local SVG generation, no external API, <5ms) |
|
||||
| Outbound HTTP | Stealth client (`devplacepy/stealth.py`): real Chrome fingerprint (TLS JA3/JA4 + HTTP/2 + headers) via `curl_cffi` behind an `httpx` transport adapter, pure-`httpx[http2]` fallback; the single client for every server-side outbound request |
|
||||
| Coverage | `coverage.py` (`.coveragerc`, subprocess-aware) |
|
||||
| Load testing | Locust (locustfile.py) |
|
||||
|
||||
@@ -79,7 +80,7 @@ devplacepy/
|
||||
| `/follow` | Follow/unfollow users |
|
||||
| `/leaderboard` | Contributor ranking by total stars earned |
|
||||
| `/avatar` | Multiavatar proxy with in-memory cache |
|
||||
| `/bugs` | Bug tracker backed by Gitea: list/detail/comment/status, AI-enhanced filing |
|
||||
| `/issues` | Issue tracker backed by Gitea: list/detail/comment/status, AI-enhanced filing |
|
||||
| `/admin/services` | Background service management (start/stop, config, status, logs) |
|
||||
| `/admin` | Admin panel (user management, news curation, settings) |
|
||||
| `/docs` | Developer documentation site with a complete, interactive HTTP API reference |
|
||||
@@ -98,7 +99,7 @@ Member progression is driven by activity and peer recognition.
|
||||
- **Leaderboard** (`/leaderboard`) ranks the top 50 members by total stars (single page, no pagination); a member's own rank is shown on their profile.
|
||||
- **Contribution heatmap and streaks.** Each profile shows a 12-month activity heatmap and the current/longest daily streak, derived from post/comment/gist/project timestamps (no extra storage).
|
||||
- **Social graph listings.** Each profile has Followers and Following tabs that paginate the follow graph (25 per page) and show a follow/unfollow control for each person. The same data is available as JSON at `GET /profile/{username}/followers` and `GET /profile/{username}/following`.
|
||||
- **Media gallery.** Each profile has a public Media tab: a responsive, paginated grid of every attachment that user uploaded across posts, projects, gists, comments, messages, bugs, and news, newest first. Images open in the shared lightbox. The owner can delete their own media and an admin can delete anyone's; deletion is a **soft delete** that hides the item everywhere (including its parent object) while preserving the file and the relation, so an admin can restore it from the **Media** trash at `/admin/media`.
|
||||
- **Media gallery.** Each profile has a public Media tab: a responsive, paginated grid of every attachment that user uploaded across posts, projects, gists, comments, messages, issues, and news, newest first. Images open in the shared lightbox. The owner can delete their own media and an admin can delete anyone's; deletion is a **soft delete** that hides the item everywhere (including its parent object) while preserving the file and the relation, so an admin can restore it from the **Media** trash at `/admin/media`.
|
||||
- **Reward notifications** fire when a member levels up or earns a badge.
|
||||
|
||||
## Engagement
|
||||
@@ -126,6 +127,8 @@ The log is **administrator-only**. `/admin/audit-log` is a paginated, filterable
|
||||
| `SECRET_KEY` | hardcoded fallback | Session signing key |
|
||||
| `DEVPLACE_VAPID_SUB` | `mailto:retoor@molodetz.nl` | Contact address in the VAPID JWT `sub` claim |
|
||||
| `DEVPLACE_INTERNAL_BASE_URL` | `http://localhost:10500` | Base URL the platform's own services dial for the AI gateway |
|
||||
| `DEVPLACE_XMLRPC_PORT` | `10550` | Loopback port the forking XML-RPC bridge binds; the app and nginx reverse-proxy `/xmlrpc` to it |
|
||||
| `DEVPLACE_XMLRPC_BIND` | `127.0.0.1` | Bind address for the XML-RPC bridge (loopback; the app and nginx are the intended front doors) |
|
||||
| `DEVPLACE_STATIC_VERSION` | server boot unix timestamp | Cache-busting version stamped into every static asset URL (`/static/v<version>/...`). Set it at launch so multiple workers agree (the `prod` target and Docker image do this); leave unset in dev to refresh on each reload. See [Static asset caching](#static-asset-caching) |
|
||||
| `DEEPSEEK_API_KEY` / `OPENROUTER_API_KEY` | unset | Upstream provider keys; migrated into the gateway settings on first boot |
|
||||
|
||||
@@ -192,6 +195,71 @@ curl -H "Accept: application/json" https://your-host/feed
|
||||
curl -H "Accept: application/json" -X POST -d "content=hi&title=T&topic=devlog" https://your-host/posts/create
|
||||
```
|
||||
|
||||
## XML-RPC bridge
|
||||
|
||||
The full REST API is also reachable over XML-RPC at `/xmlrpc`. A standalone forking XML-RPC
|
||||
server (`XmlrpcService`, supervised like any other background service, listening on the
|
||||
loopback `DEVPLACE_XMLRPC_PORT`, default `10550`) generates one method per documented endpoint
|
||||
directly from the API reference, so every capability is callable over XML-RPC with no extra
|
||||
wiring. The app reverse-proxies `/xmlrpc` to it (`routers/xmlrpc.py`); in production nginx
|
||||
forwards `/xmlrpc` as well. Method names mirror the endpoint id with dots (`posts.create`,
|
||||
`feed.list`, `profile.update`); each method takes one struct of named parameters and returns
|
||||
the same JSON payload the REST endpoint would. Authenticate with `api_key` inside the struct,
|
||||
an `X-API-KEY` / `Bearer` header, or HTTP Basic via a credentialed URL
|
||||
(`http://username:password@host/xmlrpc`). Full XML-RPC introspection (`system.listMethods`,
|
||||
`system.methodHelp`, `system.methodSignature`) and batching (`system.multicall`) are
|
||||
supported; REST errors surface as XML-RPC faults whose `faultCode` is the HTTP status. Full
|
||||
details and copy-paste Python examples (including a bot that replies to mentions) live at
|
||||
`/docs/xmlrpc.html`; runnable versions are in `examples/xmlrpc/`.
|
||||
|
||||
```python
|
||||
import xmlrpc.client
|
||||
|
||||
proxy = xmlrpc.client.ServerProxy("https://devplace.net/xmlrpc", allow_none=True)
|
||||
proxy.system.listMethods()
|
||||
proxy.posts.create({"content": "hi from xml-rpc", "api_key": "YOUR_API_KEY"})
|
||||
```
|
||||
|
||||
## devRant compatibility API
|
||||
|
||||
A second REST surface under `/api` mirrors the public devRant API shape so legacy devRant
|
||||
clients can run against DevPlace data. Rants map to posts, comments and votes map to the
|
||||
native engagement layer, and devRant integer IDs map directly onto the auto-increment `id`
|
||||
column every table already carries (`posts.id`, `comments.id`, `users.id`). Authentication
|
||||
follows the devRant model: `POST /api/users/auth-token` with `username`/`password` returns an
|
||||
`auth_token` struct (`token_id`, `token_key`, `user_id`) backed by the `devrant_tokens` table;
|
||||
every subsequent request carries that triple as query params or body fields (form or JSON both
|
||||
accepted). Writes go through the same audited helpers as the native UI, so XP, notifications,
|
||||
audit, and soft-delete all apply.
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|--------|------|---------|
|
||||
| POST | `/api/users/auth-token` | Log in (by username or email), returns `auth_token` |
|
||||
| POST | `/api/users` | Register a new account |
|
||||
| GET | `/api/get-user-id?username=` | Resolve a username to its integer id |
|
||||
| GET | `/api/users/{id}` | User profile (rants + comments) |
|
||||
| POST | `/api/users/me/edit-profile` | Update bio/location/github/website |
|
||||
| DELETE | `/api/users/me` | Deactivate account |
|
||||
| GET | `/api/devrant/rants?sort=&limit=&skip=` | Rant feed (`recent`/`top`/`algo`) |
|
||||
| POST | `/api/devrant/rants` | Post a rant (`rant`, comma-separated `tags`) |
|
||||
| GET | `/api/devrant/rants/{id}` | One rant with its comments |
|
||||
| POST | `/api/devrant/rants/{id}` | Edit a rant (owner only) |
|
||||
| DELETE | `/api/devrant/rants/{id}` | Delete a rant (owner or admin) |
|
||||
| POST | `/api/devrant/rants/{id}/vote` | Vote (`1`/`-1`/`0`) |
|
||||
| POST | `/api/devrant/rants/{id}/{favorite\|unfavorite}` | Bookmark toggle |
|
||||
| POST | `/api/devrant/rants/{id}/comments` | Comment on a rant |
|
||||
| GET | `/api/devrant/search?term=` | Search rants |
|
||||
| GET / POST / DELETE | `/api/comments/{id}` | Read / edit / delete a comment |
|
||||
| POST | `/api/comments/{id}/vote` | Vote on a comment |
|
||||
| GET / DELETE | `/api/users/me/notif-feed` | Notification feed / mark all read |
|
||||
| GET | `/api/avatars/u/{username}.png` | PNG avatar rendered from the username seed |
|
||||
|
||||
devRant `tags` round-trip verbatim via a `tags` column on `posts`; `profile_skills` is derived
|
||||
from the user bio (DevPlace has no separate skills field); avatars are real PNGs rendered from
|
||||
the local multiavatar engine. The surface is toggled by the `devrant_api_enabled` setting
|
||||
(default on). The endpoints are served at devRant's path shape; pointing a hard-coded client at
|
||||
this server is a DNS/reverse-proxy concern handled at the infrastructure layer.
|
||||
|
||||
## Documentation site
|
||||
|
||||
`/docs` serves a server-rendered docs site with a feed-style left sidebar
|
||||
@@ -223,7 +291,7 @@ pre-filled. Each panel has a response-format selector (defaulting to JSON) that
|
||||
**Expected** tab showing the modeled response, and a **Live response** tab for the real
|
||||
result. To document a new endpoint, add an entry to `docs_api.py`; the page, sidebar link,
|
||||
examples, runner, and expected-response sample are generated automatically. FastAPI's
|
||||
built-in Swagger is moved to `/swagger` so `/docs` belongs to this site. ReDoc is at `/redoc` and the raw schema at `/openapi.json`.
|
||||
built-in Swagger is moved to `/swagger` so `/docs` belongs to this site. The raw schema is at `/openapi.json`.
|
||||
|
||||
Operator pages are admin-only: `/docs/admin.html` (user/news/settings administration) and
|
||||
`/docs/services.html` (Background Services) are hidden from the sidebar and return 404 for
|
||||
@@ -264,7 +332,7 @@ and its full configuration are documented automatically - including future servi
|
||||
|
||||
`SeoService` powers the public **Tools -> SEO Diagnostics** auditor. It runs a headless-browser (Playwright) crawl of a single URL or a sitemap (capped pages) in a subprocess and runs a broad battery of checks across eleven categories: crawlability and indexing (status, redirects, HTTPS/HSTS, canonical, robots/meta-robots, sitemap, URL hygiene, mixed content), on-page meta and content (title, description, headings, language, charset, viewport, favicon, content depth), links, structured data and rich results (JSON-LD validity and required properties, microdata/RDFa), social cards (Open Graph, Twitter), Core Web Vitals and performance (LCP, CLS, FCP, TTFB, page weight, requests, DOM size, compression, caching, image optimisation, console errors), mobile and accessibility (responsive layout, tap targets, image alt, form labels), security headers, and AI/LLM-search readiness (server-rendered-vs-JS content parity, `llms.txt`, semantic HTML). It produces a weighted score and grade with per-category subscores and a recommendation for every finding. Progress streams live over `WS /tools/seo/{uid}/ws`; the full report is available at `/tools/seo/{uid}/report` (HTML or JSON). CLI: `devplace seo prune` / `devplace seo clear`. Playwright is a core dependency; `make install` fetches the Chromium browser.
|
||||
|
||||
`DeepsearchService` powers the public **Tools -> DeepSearch** researcher. Given a single research question it plans a set of diverse web search queries, crawls and reads the most relevant sources in a subprocess (plain HTTP first, headless-browser fallback for JavaScript-heavy pages, every URL SSRF-guarded), de-duplicates content, and indexes everything into a per-session ChromaDB vector collection (embeddings via the AI gateway with a local fallback). A chain of agents (summarizer, critic, linker) then synthesises a cited report with a confidence score, source diversity and explicit gap analysis. Progress streams live over `WS /tools/deepsearch/{uid}/ws`; the report is at `/tools/deepsearch/{uid}/session` (HTML or JSON) and can be exported as Markdown, JSON or PDF. A grounded chat over the session's evidence runs at `WS /tools/deepsearch/{uid}/chat` using hybrid retrieval (vector + keyword/BM25). Runs can be paused, resumed or cancelled. A cross-session URL cache avoids re-fetching pages seen by earlier runs. CLI: `devplace deepsearch prune` / `devplace deepsearch clear`. ChromaDB, weasyprint and Playwright are core dependencies.
|
||||
`DeepsearchService` powers the public **Tools -> DeepSearch** researcher. Given a single research question it plans a set of diverse web search queries, crawls and reads the most relevant sources in a subprocess (plain HTTP first, headless-browser fallback for JavaScript-heavy pages, PDF documents streamed and text-extracted, every URL SSRF-guarded), de-duplicates content, and indexes everything into a per-session ChromaDB vector collection (embeddings via the AI gateway with a local fallback). A chain of agents (summarizer, critic, linker) then synthesises a cited report with a confidence score, source diversity and explicit gap analysis. Progress streams live over `WS /tools/deepsearch/{uid}/ws`; the report is at `/tools/deepsearch/{uid}/session` (HTML or JSON) and can be exported as Markdown, JSON or PDF. A grounded chat over the session's evidence runs at `WS /tools/deepsearch/{uid}/chat` using hybrid retrieval (vector + keyword/BM25). Runs can be paused, resumed or cancelled. A cross-session URL cache avoids re-fetching pages seen by earlier runs. CLI: `devplace deepsearch prune` / `devplace deepsearch clear`. ChromaDB, weasyprint, pypdf and Playwright are core dependencies.
|
||||
|
||||
### Adding a service
|
||||
|
||||
@@ -295,7 +363,7 @@ CLI: `devplace news clear` - delete all news from local database.
|
||||
|
||||
### Bots service
|
||||
|
||||
A Playwright-driven fleet of AI personas (`devplacepy/services/bot/`) that browse and interact with a DevPlace instance: posting, commenting, voting, reacting, creating gists/projects, filing bugs, following, and messaging. It is the former standalone `dpbot.py`, refactored into a package and managed entirely from the Services tab. Disabled by default.
|
||||
A Playwright-driven fleet of AI personas (`devplacepy/services/bot/`) that browse and interact with a DevPlace instance: posting, commenting, voting, reacting, creating gists/projects, filing issues, following, and messaging. It is the former standalone `dpbot.py`, refactored into a package and managed entirely from the Services tab. Disabled by default.
|
||||
|
||||
Each persona has its own voice and its own interests: post titles are written in the persona's voice rather than copied from the source headline, news topics and post categories are weighted by personality (so different personas react to different stories), shared code snippets pass a non-triviality quality gate, and bots discuss each other's posts in threaded conversations rather than reacting in isolation.
|
||||
|
||||
@@ -467,7 +535,7 @@ response (non-2xx is returned rather than raised so API errors are readable). Bo
|
||||
guard (private and loopback addresses are refused) and a size cap. `attach_url` downloads a public
|
||||
URL on the server and stores it as a real attachment through the same pipeline as a direct upload,
|
||||
returning a uid Devii then passes in `attachment_uids` when creating a post, project, gist, comment,
|
||||
bug, or message - so a user can ask Devii to attach an image straight from the internet. Devii also
|
||||
issue, or message - so a user can ask Devii to attach an image straight from the internet. Devii also
|
||||
has external **web search** tools - `rsearch` (web/image search), `rsearch_answer` (a web-grounded
|
||||
AI answer with sources), `rsearch_chat` (direct AI chat), and `rsearch_describe_image` (vision).
|
||||
These reach an external public service rather than this platform, so platform tools are always
|
||||
@@ -547,7 +615,7 @@ recipient's preferences (see "Configurable notifications" below):
|
||||
| Upvote on your content | content owner |
|
||||
| New follower | followed user |
|
||||
| Badge earned / level-up | the user |
|
||||
| Bug-tracker update | reporter / admins |
|
||||
| Issue-tracker update | reporter / admins |
|
||||
|
||||
`create_notification` schedules delivery as a fire-and-forget async task, so a dead
|
||||
subscription or push-service error never blocks the triggering request. Delivery
|
||||
|
||||
Reference in New Issue
Block a user