Revert "feat: rename product to Screened, add PRODUCT_NAME constant to domain"

This reverts commit f2e3a876dc.
This commit is contained in:
2026-05-12 16:26:42 +02:00
parent f2e3a876dc
commit 00218366da
9 changed files with 26 additions and 31 deletions

View File

@@ -53,7 +53,7 @@ EVENT_BUS_BACKEND=db
# EVENT_BUS_BACKEND=nats
# NATS_URL=nats://localhost:4222
# NATS_MODE=jetstream # "jetstream" (default, at-least-once) or "core" (fire-and-forget)
# NATS_SUBJECT_PREFIX=screened.events
# NATS_SUBJECT_PREFIX=movies-diary.events
# NATS_STREAM_NAME=MOVIES_DIARY_EVENTS
# NATS_CONSUMER_NAME=worker

View File

@@ -1,4 +1,4 @@
# Screened
# Movies Diary
A self-hosted, server-side rendered movie logging system with a full REST API. Built in Rust — no JavaScript in the HTML interface, just HTML forms and an RSS feed. Designed to run as a lightweight widget embedded on a personal site or as a backend for third-party clients.
@@ -10,7 +10,7 @@ A self-hosted, server-side rendered movie logging system with a full REST API. B
- Movie enrichment via TMDb — full cast, crew, genres, keywords, runtime, budget/revenue, ratings; fetched automatically on movie discovery and refreshed every 30 days; exposed via `GET /api/v1/movies/{id}/profile`
- RSS/Atom feed for public subscription (global and per-user)
- JWT authentication via cookie (HTML) or Bearer token (REST API)
- ActivityPub federation — follow/unfollow remote users, accept/reject/remove followers, federated reviews broadcast as `Note` objects with `#Screened` + `#MovieTitle` hashtags, paginated outbox, boost/Announce tracking, NodeInfo discovery endpoint, shared inbox delivery, actor profile sync (bio, avatar, discoverable)
- ActivityPub federation — follow/unfollow remote users, accept/reject/remove followers, federated reviews broadcast as `Note` objects with `#MoviesDiary` + `#MovieTitle` hashtags, paginated outbox, boost/Announce tracking, NodeInfo discovery endpoint, shared inbox delivery, actor profile sync (bio, avatar, discoverable)
- Federation moderation — instance-level domain blocking (admin-managed), per-user actor blocking with `Block` activity, delivery filter excludes blocked actors and blocked-domain inboxes
- CSV and JSON diary export
- File importer: upload CSV, TSV, JSON, or XLSX from any source (Letterboxd, IMDb, etc.), map columns to domain fields via a step-by-step wizard or REST API, save mapping profiles for repeat imports

View File

@@ -6,8 +6,6 @@ pub mod review_handler;
pub(crate) mod urls;
pub mod user_adapter;
use domain::PRODUCT_NAME;
// Re-export the generic base types that callers need
pub use activitypub_base::{
ActivityPubService, ApFederationConfig, ApObjectHandler, ApUser, ApUserRepository,
@@ -48,7 +46,7 @@ pub async fn wire(
}),
base_url.clone(),
allow_registration,
PRODUCT_NAME.to_lowercase(),
"movies-diary".to_string(),
cfg!(debug_assertions),
)
.await?,

View File

@@ -69,9 +69,9 @@ pub fn review_to_ap_object(
let tag = vec![
ApHashtag {
kind: "Hashtag".to_string(),
href: Url::parse(&format!("{}/tags/screened", base_url))
href: Url::parse(&format!("{}/tags/moviesdiary", base_url))
.expect("valid base_url"),
name: "#Screened".to_string(),
name: "#MoviesDiary".to_string(),
},
ApHashtag {
kind: "Hashtag".to_string(),
@@ -137,7 +137,7 @@ mod tests {
);
assert_eq!(obj.tag.len(), 2);
let names: Vec<&str> = obj.tag.iter().map(|t| t.name.as_str()).collect();
assert!(names.contains(&"#Screened"));
assert!(names.contains(&"#MoviesDiary"));
assert!(names.contains(&"#Dune"));
}
}

View File

@@ -28,9 +28,9 @@ impl NatsConfig {
};
let subject_prefix = std::env::var("NATS_SUBJECT_PREFIX")
.unwrap_or_else(|_| "screened.events".to_string());
.unwrap_or_else(|_| "movies-diary.events".to_string());
let stream_name = std::env::var("NATS_STREAM_NAME")
.unwrap_or_else(|_| "SCREENED_EVENTS".to_string());
.unwrap_or_else(|_| "MOVIES_DIARY_EVENTS".to_string());
let consumer_name = std::env::var("NATS_CONSUMER_NAME")
.unwrap_or_else(|_| "worker".to_string());
@@ -61,8 +61,8 @@ mod tests {
let cfg = NatsConfig::from_env().unwrap();
assert_eq!(cfg.url, "nats://localhost:4222");
assert_eq!(cfg.mode, NatsMode::JetStream);
assert_eq!(cfg.subject_prefix, "screened.events");
assert_eq!(cfg.stream_name, "SCREENED_EVENTS");
assert_eq!(cfg.subject_prefix, "movies-diary.events");
assert_eq!(cfg.stream_name, "MOVIES_DIARY_EVENTS");
assert_eq!(cfg.consumer_name, "worker");
unsafe { std::env::remove_var("NATS_URL"); }

View File

@@ -9,7 +9,7 @@
content="A personal movie diary — track what you watch, rate and review films."
/>
<meta property="og:type" content="website" />
<meta property="og:site_name" content="Screened" />
<meta property="og:site_name" content="Movies Diary" />
<meta property="og:title" content="{{ ctx.page_title }}" />
<meta property="og:url" content="{{ ctx.canonical_url }}" />
<meta name="twitter:card" content="summary" />
@@ -26,7 +26,7 @@
</head>
<body>
<header>
<a href="/" class="site-title">Screened</a>
<a href="/" class="site-title">Movies Diary</a>
<nav>
<a href="/">Feed</a>
<a href="/users">Users</a>

View File

@@ -4,5 +4,3 @@ pub mod models;
pub mod ports;
pub mod services;
pub mod value_objects;
pub const PRODUCT_NAME: &str = "Screened";

View File

@@ -64,7 +64,7 @@ pub(crate) async fn build_page_context(
is_admin,
register_enabled: state.app_ctx.config.allow_registration,
rss_url: "/feed.rss".to_string(),
page_title: domain::PRODUCT_NAME.to_string(),
page_title: "Movies Diary".to_string(),
canonical_url: state.app_ctx.config.base_url.clone(),
csrf_token,
page_rss_url: None,
@@ -108,7 +108,7 @@ pub async fn get_login_page(
is_admin: false,
register_enabled: state.app_ctx.config.allow_registration,
rss_url: "/feed.rss".to_string(),
page_title: format!("Login — {}", domain::PRODUCT_NAME),
page_title: "Login — Movies Diary".to_string(),
canonical_url: format!("{}/login", state.app_ctx.config.base_url),
csrf_token: csrf.0,
page_rss_url: None,
@@ -175,7 +175,7 @@ pub async fn get_register_page(
is_admin: false,
register_enabled: true,
rss_url: "/feed.rss".to_string(),
page_title: format!("Register — {}", domain::PRODUCT_NAME),
page_title: "Register — Movies Diary".to_string(),
canonical_url: format!("{}/register", state.app_ctx.config.base_url),
csrf_token: csrf.0,
page_rss_url: None,
@@ -236,7 +236,7 @@ pub async fn get_new_review_page(
Extension(csrf): Extension<CsrfToken>,
) -> impl IntoResponse {
let mut ctx = build_page_context(&state, Some(user_id), csrf.0).await;
ctx.page_title = format!("Log a Review — {}", domain::PRODUCT_NAME);
ctx.page_title = "Log a Review — Movies Diary".to_string();
ctx.canonical_url = format!("{}/reviews/new", state.app_ctx.config.base_url);
let html = state
.html_renderer
@@ -450,7 +450,7 @@ pub async fn get_users_list(
Extension(csrf): Extension<CsrfToken>,
) -> impl IntoResponse {
let mut ctx = build_page_context(&state, user_id, csrf.0).await;
ctx.page_title = format!("Members — {}", domain::PRODUCT_NAME);
ctx.page_title = "Members — Movies Diary".to_string();
ctx.canonical_url = format!("{}/users", state.app_ctx.config.base_url);
#[cfg(feature = "federation")]
@@ -575,7 +575,7 @@ pub async fn get_user_profile(
};
let display_name = profile_user.username().value();
ctx.page_title = format!("{}'s Diary — {}", display_name, domain::PRODUCT_NAME);
ctx.page_title = format!("{}'s Diary — Movies Diary", display_name);
ctx.canonical_url = format!(
"{}/users/{}",
state.app_ctx.config.base_url, profile_user_uuid
@@ -822,7 +822,7 @@ pub async fn get_following_page(
return StatusCode::FORBIDDEN.into_response();
}
let mut ctx = build_page_context(&state, Some(user_id.clone()), csrf.0).await;
ctx.page_title = format!("Following — {}", domain::PRODUCT_NAME);
ctx.page_title = "Following — Movies Diary".to_string();
ctx.canonical_url = format!(
"{}/users/{}/following-list",
state.app_ctx.config.base_url, profile_user_uuid
@@ -872,7 +872,7 @@ pub async fn get_followers_page(
return StatusCode::FORBIDDEN.into_response();
}
let mut ctx = build_page_context(&state, Some(user_id.clone()), csrf.0).await;
ctx.page_title = format!("Followers — {}", domain::PRODUCT_NAME);
ctx.page_title = "Followers — Movies Diary".to_string();
ctx.canonical_url = format!(
"{}/users/{}/followers-list",
state.app_ctx.config.base_url, profile_user_uuid
@@ -1006,7 +1006,7 @@ pub async fn get_profile_settings(
Extension(csrf): Extension<CsrfToken>,
) -> impl IntoResponse {
let mut ctx = build_page_context(&state, Some(user_id.clone()), csrf.0).await;
ctx.page_title = format!("Profile Settings — {}", domain::PRODUCT_NAME);
ctx.page_title = "Profile Settings — Movies Diary".to_string();
ctx.canonical_url = format!("{}/settings/profile", state.app_ctx.config.base_url);
let user = match state
@@ -1061,7 +1061,7 @@ pub async fn get_blocked_domains_page(
Extension(csrf): Extension<CsrfToken>,
) -> impl IntoResponse {
let mut ctx = build_page_context(&state, Some(user_id), csrf.0).await;
ctx.page_title = format!("Blocked Domains — {}", domain::PRODUCT_NAME);
ctx.page_title = "Blocked Domains — Movies Diary".to_string();
ctx.canonical_url = format!("{}/admin/blocked-domains", state.app_ctx.config.base_url);
match state.ap_service.get_blocked_domains().await {
Ok(domains) => {
@@ -1134,7 +1134,7 @@ pub async fn get_blocked_actors_page(
Extension(csrf): Extension<CsrfToken>,
) -> impl IntoResponse {
let mut ctx = build_page_context(&state, Some(user_id.clone()), csrf.0).await;
ctx.page_title = format!("Blocked Users — {}", domain::PRODUCT_NAME);
ctx.page_title = "Blocked Users — Movies Diary".to_string();
ctx.canonical_url = format!("{}/social/blocked", state.app_ctx.config.base_url);
match state.ap_service.get_blocked_actors(user_id.value()).await {
Ok(actors) => {

View File

@@ -6,7 +6,6 @@ mod social;
mod users;
use axum::Router;
use domain::PRODUCT_NAME;
use utoipa::{
Modify, OpenApi,
openapi::security::{Http, HttpAuthScheme, SecurityScheme},
@@ -29,9 +28,9 @@ impl Modify for SecurityAddon {
fn build() -> utoipa::openapi::OpenApi {
let mut api = auth::AuthDoc::openapi();
api.info = utoipa::openapi::InfoBuilder::new()
.title(format!("{} API", PRODUCT_NAME))
.title("Movies Diary API")
.version("1.0.0")
.description(Some(format!("REST API for {}. Authenticate with `POST /api/v1/auth/login` to get a Bearer token.", PRODUCT_NAME)))
.description(Some("REST API for Movies Diary. Authenticate with `POST /api/v1/auth/login` to get a Bearer token."))
.build();
api.merge(diary::DiaryDoc::openapi());
api.merge(movies::MoviesDoc::openapi());