From 83c7d82fce4aa42a8aace0b09603a20c28982d88 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 24 Mar 2020 14:41:46 -0400 Subject: [PATCH 01/13] Changing post voting arrows. --- ui/src/components/post-listing.tsx | 8 ++++---- ui/src/components/symbols.tsx | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx index edb858ddf..ff863dcb0 100644 --- a/ui/src/components/post-listing.tsx +++ b/ui/src/components/post-listing.tsx @@ -250,14 +250,14 @@ export class PostListing extends Component {
{
{WebSocketService.Instance.site.enable_downvotes && ( )} diff --git a/ui/src/components/symbols.tsx b/ui/src/components/symbols.tsx index 1220413cb..16deec3eb 100644 --- a/ui/src/components/symbols.tsx +++ b/ui/src/components/symbols.tsx @@ -97,6 +97,12 @@ export class Symbols extends Component { + + + + + + From 4796f890fbc15df3b13cb58e25aeadb6a58da2a2 Mon Sep 17 00:00:00 2001 From: Felix Date: Thu, 26 Mar 2020 15:45:56 +0100 Subject: [PATCH 02/13] Add documentation for contributing to federation development --- docs/src/SUMMARY.md | 1 + .../contributing_federation_development.md | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 docs/src/contributing_federation_development.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 10a6153ea..70c423c79 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -13,6 +13,7 @@ - [Contributing](contributing.md) - [Docker Development](contributing_docker_development.md) - [Local Development](contributing_local_development.md) + - [Federation Development](contributing_federation_development.md) - [Websocket/HTTP API](contributing_websocket_http_api.md) - [ActivityPub API Outline](contributing_apub_api_outline.md) - [Theming Guide](contributing_theming.md) diff --git a/docs/src/contributing_federation_development.md b/docs/src/contributing_federation_development.md new file mode 100644 index 000000000..13a047d08 --- /dev/null +++ b/docs/src/contributing_federation_development.md @@ -0,0 +1,37 @@ +# Federation Development + +## Setup + +If you don't have a local clone of the Lemmy repo yet, just run the following command: + +```bash +git clone https://yerbamate.dev/nutomic/lemmy.git -b federation +``` + +If you already have the Lemmy repo cloned, you need to add a new remote: +```bash +git remote add federation https://yerbamate.dev/nutomic/lemmy.git +git checkout federation +git pull federation federation +``` + +## Running + +You need to have the following packages installed, the Docker service needs to be running. + +- docker +- docker-compose +- cargo +- yarn + +Then run the following +```bash +cd dev/federation-test +./run-federation-test.bash +``` + +After the build is finished and the docker-compose setup is running, open [127.0.0.1:8540](http://127.0.0.1:8540) and +[127.0.0.1:8541](http://127.0.0.1:8541) in your browser to use the test instances. You can login as admin with +username `lemmy` and password `lemmy`, or create new accounts. + +Please get in touch if you want to contribute to this, so we can coordinate things and avoid duplicate work. \ No newline at end of file From bafc2fc7acf3e522df04a74e27f604fb95e6bd01 Mon Sep 17 00:00:00 2001 From: Felix Date: Sat, 28 Mar 2020 16:56:20 +0100 Subject: [PATCH 03/13] Convert md to html for feeds, try to deduplicate code --- server/Cargo.lock | 11 +++ server/Cargo.toml | 1 + server/src/routes/feeds.rs | 198 +++++++++++++++++-------------------- 3 files changed, 100 insertions(+), 110 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index f6ce65507..265abfc78 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "Markdown-to-HTML-rs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "activitypub" version = "0.2.0" @@ -1369,6 +1378,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "lemmy_server" version = "0.0.1" dependencies = [ + "Markdown-to-HTML-rs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2823,6 +2833,7 @@ dependencies = [ ] [metadata] +"checksum Markdown-to-HTML-rs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1a9bda9d68f643d9b63888996896ce5be873d0f22fe1c859bce84dd4bd4661b" "checksum activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d538a21b137ec0f63cc579ef4afa4ab13aa85b4f8af15a033683edd97c50718d" "checksum activitystreams-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65608fdeae5eb05485d5b71a3d2242d76b2b7413608c196d47eb4dff3eed7b85" "checksum activitystreams-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c2a3958d240f40eff1f31b5f679a6e0d4ce2a16812886a3ec0164f3a2ca517" diff --git a/server/Cargo.toml b/server/Cargo.toml index 156ccb87a..3803485b4 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -36,3 +36,4 @@ config = "0.10.1" hjson = "0.8.2" percent-encoding = "2.1.0" isahc = "0.9" +Markdown-to-HTML-rs = "0.1.0" diff --git a/server/src/routes/feeds.rs b/server/src/routes/feeds.rs index ad0f28d5a..c94a60d45 100644 --- a/server/src/routes/feeds.rs +++ b/server/src/routes/feeds.rs @@ -10,7 +10,7 @@ use crate::db::user_mention_view::{UserMentionQueryBuilder, UserMentionView}; use crate::db::{ListingType, SortType}; use crate::Settings; use actix_web::{web, HttpResponse, Result}; -use chrono::{DateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, Utc}; use diesel::r2d2::{ConnectionManager, Pool}; use diesel::PgConnection; use failure::Error; @@ -18,6 +18,7 @@ use rss::{CategoryBuilder, ChannelBuilder, GuidBuilder, Item, ItemBuilder}; use serde::Deserialize; use std::str::FromStr; use strum::ParseError; +extern crate Markdown_to_HTML_rs; #[derive(Deserialize)] pub struct Params { @@ -34,7 +35,6 @@ enum RequestType { pub fn config(cfg: &mut web::ServiceConfig) { cfg .route("/feeds/{type}/{name}.xml", web::get().to(feeds::get_feed)) - .route("/feeds/all.xml", web::get().to(feeds::get_all_feed)) .route("/feeds/all.xml", web::get().to(feeds::get_all_feed)); } @@ -44,9 +44,7 @@ async fn get_all_feed( ) -> Result { let res = web::block(move || { let conn = db.get()?; - - let sort_type = get_sort_type(info)?; - get_feed_all_data(&conn, &sort_type) + get_feed_all_data(&conn, &get_sort_type(info)?) }) .await .map(|rss| { @@ -58,6 +56,29 @@ async fn get_all_feed( Ok(res) } +fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result { + let site_view = SiteView::read(&conn)?; + + let posts = PostQueryBuilder::create(&conn) + .listing_type(ListingType::All) + .sort(sort_type) + .list()?; + + let items = create_post_items(posts); + + let mut channel_builder = ChannelBuilder::default(); + channel_builder + .title(&format!("{} - All", site_view.name)) + .link(format!("https://{}", Settings::get().hostname)) + .items(items); + + if let Some(site_desc) = site_view.description { + channel_builder.description(&site_desc); + } + + Ok(channel_builder.build().unwrap().to_string()) +} + async fn get_feed( path: web::Path<(String, String)>, info: web::Query, @@ -86,6 +107,7 @@ async fn get_feed( } }) .await + .map(|builder| builder.build().unwrap().to_string()) .map(|rss| { HttpResponse::Ok() .content_type("application/rss+xml") @@ -103,34 +125,11 @@ fn get_sort_type(info: web::Query) -> Result { SortType::from_str(&sort_query) } -fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result { - let site_view = SiteView::read(&conn)?; - - let posts = PostQueryBuilder::create(&conn) - .listing_type(ListingType::All) - .sort(sort_type) - .list()?; - - let items = create_post_items(posts); - - let mut channel_builder = ChannelBuilder::default(); - channel_builder - .title(&format!("{} - All", site_view.name)) - .link(format!("https://{}", Settings::get().hostname)) - .items(items); - - if let Some(site_desc) = site_view.description { - channel_builder.description(&site_desc); - } - - Ok(channel_builder.build().unwrap().to_string()) -} - fn get_feed_user( conn: &PgConnection, sort_type: &SortType, user_name: String, -) -> Result { +) -> Result { let site_view = SiteView::read(&conn)?; let user = User_::find_by_username(&conn, &user_name)?; let user_url = user.get_profile_url(); @@ -149,14 +148,14 @@ fn get_feed_user( .link(user_url) .items(items); - Ok(channel_builder.build().unwrap().to_string()) + Ok(channel_builder) } fn get_feed_community( conn: &PgConnection, sort_type: &SortType, community_name: String, -) -> Result { +) -> Result { let site_view = SiteView::read(&conn)?; let community = Community::read_from_name(&conn, community_name)?; let community_url = community.get_url(); @@ -179,10 +178,14 @@ fn get_feed_community( channel_builder.description(&community_desc); } - Ok(channel_builder.build().unwrap().to_string()) + Ok(channel_builder) } -fn get_feed_front(conn: &PgConnection, sort_type: &SortType, jwt: String) -> Result { +fn get_feed_front( + conn: &PgConnection, + sort_type: &SortType, + jwt: String, +) -> Result { let site_view = SiteView::read(&conn)?; let user_id = Claims::decode(&jwt)?.claims.id; @@ -204,10 +207,10 @@ fn get_feed_front(conn: &PgConnection, sort_type: &SortType, jwt: String) -> Res channel_builder.description(&site_desc); } - Ok(channel_builder.build().unwrap().to_string()) + Ok(channel_builder) } -fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result { +fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result { let site_view = SiteView::read(&conn)?; let user_id = Claims::decode(&jwt)?.claims.id; @@ -233,86 +236,61 @@ fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result { channel_builder.description(&site_desc); } - Ok(channel_builder.build().unwrap().to_string()) + Ok(channel_builder) } fn create_reply_and_mention_items( replies: Vec, mentions: Vec, ) -> Vec { - let mut items: Vec = Vec::new(); + let mut reply_items: Vec = replies + .iter() + .map(|r| { + let reply_url = format!( + "https://{}/post/{}/comment/{}", + Settings::get().hostname, + r.post_id, + r.id + ); + build_item(&r.creator_name, &r.published, &reply_url, &r.content) + }) + .collect(); - for r in replies { - let mut i = ItemBuilder::default(); + let mut mention_items: Vec = mentions + .iter() + .map(|m| { + let mention_url = format!( + "https://{}/post/{}/comment/{}", + Settings::get().hostname, + m.post_id, + m.id + ); + build_item(&m.creator_name, &m.published, &mention_url, &m.content) + }) + .collect(); - i.title(format!("Reply from {}", r.creator_name)); + reply_items.append(&mut mention_items); + reply_items +} - let author_url = format!("https://{}/u/{}", Settings::get().hostname, r.creator_name); - i.author(format!( - "/u/{} (link)", - r.creator_name, author_url - )); - - let dt = DateTime::::from_utc(r.published, Utc); - i.pub_date(dt.to_rfc2822()); - - let reply_url = format!( - "https://{}/post/{}/comment/{}", - Settings::get().hostname, - r.post_id, - r.id - ); - i.comments(reply_url.to_owned()); - let guid = GuidBuilder::default() - .permalink(true) - .value(&reply_url) - .build(); - i.guid(guid.unwrap()); - - i.link(reply_url); - - // TODO find a markdown to html parser here, do images, etc - i.description(r.content); - - items.push(i.build().unwrap()); - } - - for m in mentions { - let mut i = ItemBuilder::default(); - - i.title(format!("Mention from {}", m.creator_name)); - - let author_url = format!("https://{}/u/{}", Settings::get().hostname, m.creator_name); - i.author(format!( - "/u/{} (link)", - m.creator_name, author_url - )); - - let dt = DateTime::::from_utc(m.published, Utc); - i.pub_date(dt.to_rfc2822()); - - let mention_url = format!( - "https://{}/post/{}/comment/{}", - Settings::get().hostname, - m.post_id, - m.id - ); - i.comments(mention_url.to_owned()); - let guid = GuidBuilder::default() - .permalink(true) - .value(&mention_url) - .build(); - i.guid(guid.unwrap()); - - i.link(mention_url); - - // TODO find a markdown to html parser here, do images, etc - i.description(m.content); - - items.push(i.build().unwrap()); - } - - items +fn build_item(creator_name: &str, published: &NaiveDateTime, url: &str, content: &str) -> Item { + let mut i = ItemBuilder::default(); + i.title(format!("Reply from {}", creator_name)); + let author_url = format!("https://{}/u/{}", Settings::get().hostname, creator_name); + i.author(format!( + "/u/{} (link)", + creator_name, author_url + )); + let dt = DateTime::::from_utc(*published, Utc); + i.pub_date(dt.to_rfc2822()); + i.comments(url.to_owned()); + let guid = GuidBuilder::default().permalink(true).value(url).build(); + i.guid(guid.unwrap()); + i.link(url.to_owned()); + // TODO add images + let html = Markdown_to_HTML_rs::replace_all(&content.to_string()); + i.description(html); + i.build().unwrap() } fn create_post_items(posts: Vec) -> Vec { @@ -359,9 +337,8 @@ fn create_post_items(posts: Vec) -> Vec { i.link(url); } - // TODO find a markdown to html parser here, do images, etc - let mut description = format!(" - submitted by {} to {}
{} points | {} comments", + // TODO add images + let mut description = format!("submitted by {} to {}
{} points | {} comments", author_url, p.creator_name, community_url, @@ -371,7 +348,8 @@ fn create_post_items(posts: Vec) -> Vec { p.number_of_comments); if let Some(body) = p.body { - description.push_str(&format!("

{}", body)); + let html = Markdown_to_HTML_rs::replace_all(&body); + description.push_str(&format!("

{}", html)); } i.description(description); From a789e4db2ac5ee20c66c5b32a71186a3f6171839 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sat, 28 Mar 2020 15:43:56 -0400 Subject: [PATCH 04/13] Adding a resource to docs. --- docs/src/about_goals.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/about_goals.md b/docs/src/about_goals.md index b78c78182..caa6948a0 100644 --- a/docs/src/about_goals.md +++ b/docs/src/about_goals.md @@ -50,3 +50,4 @@ - [Federation.md](https://github.com/dariusk/gathio/blob/7fc93dbe9d4d99457a0e85c6c532112f415b7af2/FEDERATION.md) - [Activitypub implementers guide](https://socialhub.activitypub.rocks/t/draft-guide-for-new-activitypub-implementers/479) - [Data storage questions](https://socialhub.activitypub.rocks/t/data-storage-questions/579/3) +- [Activitypub as it has been understood](https://flak.tedunangst.com/post/ActivityPub-as-it-has-been-understood) From 1571a4acd47f4efd52c963411ef5470428e07f02 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sat, 28 Mar 2020 18:02:49 -0400 Subject: [PATCH 05/13] Changing markdown parser to comrak. Moving crate imports to lib.rs. --- server/Cargo.lock | 181 +++++++++++++++++++++++++++++++--- server/Cargo.toml | 2 +- server/src/db/mod.rs | 1 - server/src/lib.rs | 6 ++ server/src/routes/feeds.rs | 11 +-- server/src/routes/nodeinfo.rs | 1 - server/src/settings.rs | 1 - 7 files changed, 181 insertions(+), 22 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 265abfc78..2a3bc0330 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1,14 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "Markdown-to-HTML-rs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "activitypub" version = "0.2.0" @@ -387,6 +378,14 @@ dependencies = [ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arc-swap" version = "0.4.4" @@ -638,6 +637,20 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -646,6 +659,22 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "comrak" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "twoway 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "config" version = "0.10.1" @@ -951,6 +980,11 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "entities" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "enum-as-inner" version = "0.3.2" @@ -1378,7 +1412,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "lemmy_server" version = "0.0.1" dependencies = [ - "Markdown-to-HTML-rs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1387,6 +1420,7 @@ dependencies = [ "actix-web-actors 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bcrypt 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "comrak 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1517,6 +1551,11 @@ dependencies = [ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "match_cfg" version = "0.1.0" @@ -1792,6 +1831,45 @@ name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_generator 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_generator" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_meta" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pin-project" version = "0.4.8" @@ -2300,6 +2378,17 @@ dependencies = [ "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha1" version = "0.6.0" @@ -2382,6 +2471,11 @@ name = "strsim" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.9.3" @@ -2445,6 +2539,14 @@ dependencies = [ "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thiserror" version = "1.0.11" @@ -2584,11 +2686,35 @@ dependencies = [ "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "twoway" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unchecked-index 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typed-arena" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "typenum" version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unchecked-index" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicase" version = "2.6.0" @@ -2618,11 +2744,21 @@ name = "unicode-segmentation" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "untrusted" version = "0.7.0" @@ -2684,6 +2820,11 @@ name = "vcpkg" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "version_check" version = "0.1.5" @@ -2833,7 +2974,6 @@ dependencies = [ ] [metadata] -"checksum Markdown-to-HTML-rs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1a9bda9d68f643d9b63888996896ce5be873d0f22fe1c859bce84dd4bd4661b" "checksum activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d538a21b137ec0f63cc579ef4afa4ab13aa85b4f8af15a033683edd97c50718d" "checksum activitystreams-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65608fdeae5eb05485d5b71a3d2242d76b2b7413608c196d47eb4dff3eed7b85" "checksum activitystreams-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c2a3958d240f40eff1f31b5f679a6e0d4ce2a16812886a3ec0164f3a2ca517" @@ -2859,6 +2999,7 @@ dependencies = [ "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum ascii_utils 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" @@ -2891,7 +3032,9 @@ dependencies = [ "checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum comrak 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e17058cc536cf290563e88787d7b9e6030ce4742943017cc2ffb71f88034021c" "checksum config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" "checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" "checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" @@ -2925,6 +3068,7 @@ dependencies = [ "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" +"checksum entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" "checksum enum-as-inner 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" @@ -2985,6 +3129,7 @@ dependencies = [ "checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum match_cfg 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" @@ -3016,6 +3161,10 @@ dependencies = [ "checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum pem 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1581760c757a756a41f0ee3ff01256227bdf64cb752839779b95ffb01c59793" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +"checksum pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +"checksum pest_generator 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +"checksum pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" "checksum pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" "checksum pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" "checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" @@ -3077,6 +3226,7 @@ dependencies = [ "checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" "checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" @@ -3088,6 +3238,7 @@ dependencies = [ "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" "checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" "checksum strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" "checksum strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" @@ -3095,6 +3246,7 @@ dependencies = [ "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db" "checksum thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" @@ -3107,12 +3259,18 @@ dependencies = [ "checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" "checksum trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" "checksum trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" +"checksum twoway 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc" +"checksum typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum ucd-trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +"checksum unchecked-index 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" "checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" @@ -3121,6 +3279,7 @@ dependencies = [ "checksum v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" "checksum v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" "checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" diff --git a/server/Cargo.toml b/server/Cargo.toml index 3803485b4..5a4fdcece 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -36,4 +36,4 @@ config = "0.10.1" hjson = "0.8.2" percent-encoding = "2.1.0" isahc = "0.9" -Markdown-to-HTML-rs = "0.1.0" +comrak = "0.7" diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index dacdb6f6a..e0d358ffe 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -1,4 +1,3 @@ -extern crate lazy_static; use crate::settings::Settings; use diesel::dsl::*; use diesel::result::Error; diff --git a/server/src/lib.rs b/server/src/lib.rs index 01f01ff10..8257dab9a 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -11,12 +11,14 @@ pub extern crate actix; pub extern crate actix_web; pub extern crate bcrypt; pub extern crate chrono; +pub extern crate comrak; pub extern crate dotenv; pub extern crate jsonwebtoken; pub extern crate lettre; pub extern crate lettre_email; pub extern crate rand; pub extern crate regex; +pub extern crate rss; pub extern crate serde; pub extern crate serde_json; pub extern crate sha2; @@ -218,6 +220,10 @@ fn fetch_iframely_and_pictshare_data( ) } +pub fn markdown_to_html(text: &str) -> String { + comrak::markdown_to_html(text, &comrak::ComrakOptions::default()) +} + #[cfg(test)] mod tests { use crate::{extract_usernames, is_email_regex, remove_slurs, slur_check, slurs_vec_to_str}; diff --git a/server/src/routes/feeds.rs b/server/src/routes/feeds.rs index c94a60d45..6826cf5cb 100644 --- a/server/src/routes/feeds.rs +++ b/server/src/routes/feeds.rs @@ -1,5 +1,3 @@ -extern crate rss; - use super::*; use crate::db::comment_view::{ReplyQueryBuilder, ReplyView}; use crate::db::community::Community; @@ -8,7 +6,7 @@ use crate::db::site_view::SiteView; use crate::db::user::{Claims, User_}; use crate::db::user_mention_view::{UserMentionQueryBuilder, UserMentionView}; use crate::db::{ListingType, SortType}; -use crate::Settings; +use crate::{markdown_to_html, Settings}; use actix_web::{web, HttpResponse, Result}; use chrono::{DateTime, NaiveDateTime, Utc}; use diesel::r2d2::{ConnectionManager, Pool}; @@ -18,7 +16,6 @@ use rss::{CategoryBuilder, ChannelBuilder, GuidBuilder, Item, ItemBuilder}; use serde::Deserialize; use std::str::FromStr; use strum::ParseError; -extern crate Markdown_to_HTML_rs; #[derive(Deserialize)] pub struct Params { @@ -288,7 +285,7 @@ fn build_item(creator_name: &str, published: &NaiveDateTime, url: &str, content: i.guid(guid.unwrap()); i.link(url.to_owned()); // TODO add images - let html = Markdown_to_HTML_rs::replace_all(&content.to_string()); + let html = markdown_to_html(&content.to_string()); i.description(html); i.build().unwrap() } @@ -348,8 +345,8 @@ fn create_post_items(posts: Vec) -> Vec { p.number_of_comments); if let Some(body) = p.body { - let html = Markdown_to_HTML_rs::replace_all(&body); - description.push_str(&format!("

{}", html)); + let html = markdown_to_html(&body); + description.push_str(&html); } i.description(description); diff --git a/server/src/routes/nodeinfo.rs b/server/src/routes/nodeinfo.rs index 75568608e..1263cef84 100644 --- a/server/src/routes/nodeinfo.rs +++ b/server/src/routes/nodeinfo.rs @@ -1,4 +1,3 @@ -extern crate lazy_static; use crate::db::site_view::SiteView; use crate::version; use crate::Settings; diff --git a/server/src/settings.rs b/server/src/settings.rs index ee3a3c072..d04ea8802 100644 --- a/server/src/settings.rs +++ b/server/src/settings.rs @@ -1,4 +1,3 @@ -extern crate lazy_static; use config::{Config, ConfigError, Environment, File}; use serde::Deserialize; use std::env; From 36312e91e4533151a9b081f3f72360d880287599 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sat, 28 Mar 2020 18:18:20 -0400 Subject: [PATCH 06/13] Revert "Deploy multiple Lemmy instances to the same server (ref #474)" This reverts commit aa341933da04a21f9bb342b3b2840ee2acde8a94. --- .gitignore | 1 - ansible/lemmy_dev.yml | 50 ++++++---------------------- ansible/templates/docker-compose.yml | 6 ++-- ansible/templates/nginx.conf | 14 ++++---- ansible/uninstall.yml | 16 +++++++-- 5 files changed, 33 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index ef03389c7..9f7fa1e3c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ ansible/inventory ansible/inventory_dev ansible/passwords/ -ansible/vars/ docker/lemmy_mine.hjson docker/dev/env_deploy.sh build/ diff --git a/ansible/lemmy_dev.yml b/ansible/lemmy_dev.yml index 1d8e40aee..e9b8364f3 100644 --- a/ansible/lemmy_dev.yml +++ b/ansible/lemmy_dev.yml @@ -16,32 +16,6 @@ - setup: # gather facts tasks: - # TODO: this task is running on all hosts at the same time so there is a race condition - - name: xxx - shell: | - mkdir -p "vars/{{ inventory_hostname }}/" - if [ ! -f "vars/{{ inventory_hostname }}/port_counter" ]; then - if [ -f "vars/max_port_counter" ]; then - MAX_PORT=$(cat vars/max_port_counter) - else - MAX_PORT=8000 - fi - OUR_PORT=$(expr $MAX_PORT + 10) - echo $OUR_PORT > "vars/{{ inventory_hostname }}/port_counter" - echo $OUR_PORT > "vars/max_port_counter" - fi - cat "vars/{{ inventory_hostname }}/port_counter" - args: - executable: /bin/bash - delegate_to: localhost - register: lemmy_port - - - set_fact: "lemmy_port={{ lemmy_port.stdout_lines[0] }}" - - set_fact: "pictshare_port={{ lemmy_port|int + 1 }}" - - set_fact: "iframely_port={{ lemmy_port|int + 2 }}" - - debug: - msg: "lemmy_port={{ lemmy_port }} pictshare_port={{pictshare_port}} iframely_port={{iframely_port}}" - - name: install dependencies apt: pkg: ['nginx', 'docker-compose', 'docker.io', 'certbot', 'python-certbot-nginx'] @@ -51,29 +25,25 @@ args: creates: '/etc/letsencrypt/live/{{domain}}/privkey.pem' - # TODO: need to use different path per domain - name: create lemmy folder file: path={{item.path}} state=directory with_items: - - { path: '/lemmy/{{ domain }}/' } - - { path: '/lemmy/{{ domain }}/volumes/' } - - { path: '/var/cache/lemmy/{{ domain }}/' } + - { path: '/lemmy/' } + - { path: '/lemmy/volumes/' } - block: - name: add template files template: src={{item.src}} dest={{item.dest}} mode={{item.mode}} with_items: - - { src: 'templates/docker-compose.yml', dest: '/lemmy/{{domain}}/docker-compose.yml', mode: '0600' } - - { src: 'templates/nginx.conf', dest: '/etc/nginx/sites-enabled/lemmy-{{ domain }}.conf', mode: '0644' } - - { src: '../docker/iframely.config.local.js', dest: '/lemmy/{{ domain }}/iframely.config.local.js', mode: '0600' } + - { src: 'templates/docker-compose.yml', dest: '/lemmy/docker-compose.yml', mode: '0600' } + - { src: 'templates/nginx.conf', dest: '/etc/nginx/sites-enabled/lemmy.conf', mode: '0644' } + - { src: '../docker/iframely.config.local.js', dest: '/lemmy/iframely.config.local.js', mode: '0600' } - name: add config file (only during initial setup) - template: src='templates/config.hjson' dest='/lemmy/{{domain}}/lemmy.hjson' mode='0600' force='no' owner='1000' group='1000' + template: src='templates/config.hjson' dest='/lemmy/lemmy.hjson' mode='0600' force='no' owner='1000' group='1000' vars: - # TODO: these paths are changed, need to move the files - # TODO: not sure what to call the local var folder, its not mentioned in the ansible docs - postgres_password: "{{ lookup('password', 'vars/{{ inventory_hostname }}/postgres_password chars=ascii_letters,digits') }}" - jwt_password: "{{ lookup('password', 'vars/{{ inventory_hostname }}/jwt_password chars=ascii_letters,digits') }}" + postgres_password: "{{ lookup('password', 'passwords/{{ inventory_hostname }}/postgres chars=ascii_letters,digits') }}" + jwt_password: "{{ lookup('password', 'passwords/{{ inventory_hostname }}/jwt chars=ascii_letters,digits') }}" - name: build the dev docker image local_action: shell cd .. && sudo docker build . -f docker/dev/Dockerfile -t lemmy:dev @@ -115,7 +85,7 @@ # be a problem for testing - name: start docker-compose docker_compose: - project_src: "/lemmy/{{ domain }}/" + project_src: /lemmy/ state: present recreate: always ignore_errors: yes @@ -126,6 +96,6 @@ - name: certbot renewal cronjob cron: special_time=daily - name=certbot-renew-lemmy-{{ domain }} + name=certbot-renew-lemmy user=root job="certbot certonly --nginx -d '{{ domain }}' --deploy-hook 'nginx -s reload'" diff --git a/ansible/templates/docker-compose.yml b/ansible/templates/docker-compose.yml index d6afd2532..a4d54f6d8 100644 --- a/ansible/templates/docker-compose.yml +++ b/ansible/templates/docker-compose.yml @@ -4,7 +4,7 @@ services: lemmy: image: {{ lemmy_docker_image }} ports: - - "127.0.0.1:{{ lemmy_port }}:8536" + - "127.0.0.1:8536:8536" restart: always environment: - RUST_LOG=error @@ -28,7 +28,7 @@ services: pictshare: image: shtripok/pictshare:latest ports: - - "127.0.0.1:{{ pictshare_port }}:80" + - "127.0.0.1:8537:80" volumes: - ./volumes/pictshare:/usr/share/nginx/html/data restart: always @@ -36,7 +36,7 @@ services: iframely: image: dogbin/iframely:latest ports: - - "127.0.0.1:{{ iframely_port }}:80" + - "127.0.0.1:8061:80" volumes: - ./iframely.config.local.js:/iframely/config.local.js:ro restart: always diff --git a/ansible/templates/nginx.conf b/ansible/templates/nginx.conf index 003720bcb..04e5a6436 100644 --- a/ansible/templates/nginx.conf +++ b/ansible/templates/nginx.conf @@ -1,4 +1,4 @@ -proxy_cache_path /var/cache/lemmy/{{ domain }} levels=1:2 keys_zone=lemmy_frontend_cache_{{ domain }}:10m max_size=100m use_temp_path=off; +proxy_cache_path /var/cache/lemmy_frontend levels=1:2 keys_zone=lemmy_frontend_cache:10m max_size=100m use_temp_path=off; server { listen 80; @@ -52,7 +52,7 @@ server { client_max_body_size 50M; location / { - proxy_pass http://0.0.0.0:{{ lemmy_port }}; + proxy_pass http://0.0.0.0:8536; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -63,7 +63,7 @@ server { proxy_set_header Connection "upgrade"; # Proxy Cache - proxy_cache lemmy_frontend_cache_{{ domain }}; + proxy_cache lemmy_frontend_cache; proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504; proxy_cache_revalidate on; proxy_cache_lock on; @@ -71,7 +71,7 @@ server { } location /pictshare/ { - proxy_pass http://0.0.0.0:{{ pictshare_port }}/; + proxy_pass http://0.0.0.0:8537/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -82,7 +82,7 @@ server { } location /iframely/ { - proxy_pass http://0.0.0.0:{{ iframely_port }}/; + proxy_pass http://0.0.0.0:8061/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -98,6 +98,6 @@ map $remote_addr $remote_addr_anon { ::1 $remote_addr; default 0.0.0.0; } -log_format main_{{ domain }} '$remote_addr_anon - $remote_user [$time_local] "$request" ' +log_format main '$remote_addr_anon - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent"'; -access_log /var/log/nginx/access.log main_{{ domain }}; +access_log /var/log/nginx/access.log main; diff --git a/ansible/uninstall.yml b/ansible/uninstall.yml index 08d5316c3..252c5bd1f 100644 --- a/ansible/uninstall.yml +++ b/ansible/uninstall.yml @@ -22,14 +22,24 @@ - name: stop docker-compose docker_compose: - project_src: /lemmy/{{domain}}/ + project_src: /lemmy/ state: absent - name: delete data file: path={{item.path}} state=absent with_items: - - { path: '/lemmy/{{domain}}/' } - - { path: '/etc/nginx/sites-enabled/lemmy-{{ domain }}.conf' } + - { path: '/lemmy/' } + - { path: '/etc/nginx/sites-enabled/lemmy.conf' } + + - name: Remove a volume + docker_volume: name={{item.name}} state=absent + with_items: + - { name: 'lemmy_lemmy_db' } + - { name: 'lemmy_lemmy_pictshare' } + + - name: delete entire ecloud folder + file: path='/mnt/repo-base/' state=absent + when: delete_certs|bool - name: remove certbot cronjob cron: From bd09fe95568f89feeab7980ffe74340a4e84c875 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sat, 28 Mar 2020 18:21:10 -0400 Subject: [PATCH 07/13] Testing out another travis build. #397 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d765ecb4f..602a8613d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,6 @@ before_cache: - rm -rfv target/debug/build/lemmy_server-* - rm -rfv target/debug/deps/lemmy_server-* - rm -rfv target/debug/lemmy_server.d - - cargo clean before_script: - psql -c "create user lemmy with password 'password' superuser;" -U postgres - psql -c 'create database lemmy with owner lemmy;' -U postgres From 76bf71162ef187d2d363b29faa40d24fecdfba3b Mon Sep 17 00:00:00 2001 From: Felix Date: Thu, 26 Mar 2020 15:23:15 +0100 Subject: [PATCH 08/13] Automatic instance setup based on config variables (fixes #404) --- docker/lemmy.hjson | 11 ++++++++- server/config/defaults.hjson | 11 +++++++++ server/src/api/site.rs | 48 ++++++++++++++++++++++++++++-------- server/src/api/user.rs | 14 +++++------ server/src/settings.rs | 9 +++++++ 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/docker/lemmy.hjson b/docker/lemmy.hjson index 5a6d1ff11..b61ea8261 100644 --- a/docker/lemmy.hjson +++ b/docker/lemmy.hjson @@ -41,7 +41,16 @@ # interval length for registration limit register_per_second: 3600 } -# # email sending configuration +# # optional: parameters for automatic configuration of new instance (only used at first start) +# setup: { +# # username for the admin user +# admin_username: "lemmy" +# # password for the admin user +# admin_password: "lemmy" +# # name of the site (can be changed later) +# site_name: "Lemmy Test" +# } +# # optional: email sending configuration # email: { # # hostname of the smtp server # smtp_server: "" diff --git a/server/config/defaults.hjson b/server/config/defaults.hjson index 2b37f3bb3..97b9429c1 100644 --- a/server/config/defaults.hjson +++ b/server/config/defaults.hjson @@ -1,4 +1,15 @@ { +# # optional: parameters for automatic configuration of new instance (only used at first start) +# setup: { +# # username for the admin user +# admin_username: "" +# # password for the admin user +# admin_password: "" +# # optional: email for the admin user (can be omitted and set later through the website) +# admin_email: "" +# # name of the site (can be changed later) +# site_name: "" +# } # settings related to the postgresql database database: { # username to connect to postgres diff --git a/server/src/api/site.rs b/server/src/api/site.rs index ef1a28287..6bd90149b 100644 --- a/server/src/api/site.rs +++ b/server/src/api/site.rs @@ -1,5 +1,9 @@ use super::*; +use crate::api::user::Register; +use crate::api::{Oper, Perform}; +use crate::settings::Settings; use diesel::PgConnection; +use log::info; use std::str::FromStr; #[derive(Serialize, Deserialize)] @@ -53,12 +57,12 @@ pub struct GetModlogResponse { #[derive(Serialize, Deserialize)] pub struct CreateSite { - name: String, - description: Option, - enable_downvotes: bool, - open_registration: bool, - enable_nsfw: bool, - auth: String, + pub name: String, + pub description: Option, + pub enable_downvotes: bool, + pub open_registration: bool, + pub enable_nsfw: bool, + pub auth: String, } #[derive(Serialize, Deserialize)] @@ -277,10 +281,34 @@ impl Perform for Oper { fn perform(&self, conn: &PgConnection) -> Result { let _data: &GetSite = &self.data; - // It can return a null site in order to redirect - let site_view = match Site::read(&conn, 1) { - Ok(_site) => Some(SiteView::read(&conn)?), - Err(_e) => None, + let site = Site::read(&conn, 1); + let site_view = if site.is_ok() { + Some(SiteView::read(&conn)?) + } else if let Some(setup) = Settings::get().setup.as_ref() { + let register = Register { + username: setup.admin_username.to_owned(), + email: setup.admin_email.to_owned(), + password: setup.admin_password.to_owned(), + password_verify: setup.admin_password.to_owned(), + admin: true, + show_nsfw: true, + }; + let login_response = Oper::new(register).perform(&conn)?; + info!("Admin {} created", setup.admin_username); + + let create_site = CreateSite { + name: setup.site_name.to_owned(), + description: None, + enable_downvotes: false, + open_registration: false, + enable_nsfw: false, + auth: login_response.jwt, + }; + Oper::new(create_site).perform(&conn)?; + info!("Site {} created", setup.site_name); + Some(SiteView::read(&conn)?) + } else { + None }; let mut admins = UserView::admins(&conn)?; diff --git a/server/src/api/user.rs b/server/src/api/user.rs index 333fd9494..056a2a846 100644 --- a/server/src/api/user.rs +++ b/server/src/api/user.rs @@ -14,12 +14,12 @@ pub struct Login { #[derive(Serialize, Deserialize)] pub struct Register { - username: String, - email: Option, - password: String, - password_verify: String, - admin: bool, - show_nsfw: bool, + pub username: String, + pub email: Option, + pub password: String, + pub password_verify: String, + pub admin: bool, + pub show_nsfw: bool, } #[derive(Serialize, Deserialize)] @@ -42,7 +42,7 @@ pub struct SaveUserSettings { #[derive(Serialize, Deserialize)] pub struct LoginResponse { - jwt: String, + pub jwt: String, } #[derive(Serialize, Deserialize)] diff --git a/server/src/settings.rs b/server/src/settings.rs index ee3a3c072..a2d61edbe 100644 --- a/server/src/settings.rs +++ b/server/src/settings.rs @@ -9,6 +9,7 @@ static CONFIG_FILE: &str = "config/config.hjson"; #[derive(Debug, Deserialize)] pub struct Settings { + pub setup: Option, pub database: Database, pub hostname: String, pub bind: IpAddr, @@ -20,6 +21,14 @@ pub struct Settings { pub federation_enabled: bool, } +#[derive(Debug, Deserialize)] +pub struct Setup { + pub admin_username: String, + pub admin_password: String, + pub admin_email: Option, + pub site_name: String, +} + #[derive(Debug, Deserialize)] pub struct RateLimitConfig { pub message: i32, From 3c2a2a0adfb778cb4e781e79b1eb3bcd92c6f683 Mon Sep 17 00:00:00 2001 From: Felix Date: Tue, 31 Mar 2020 02:06:31 +0200 Subject: [PATCH 09/13] Improve installation docs --- docs/src/administration_install_ansible.md | 9 +++++++++ docs/src/administration_install_docker.md | 18 +++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/docs/src/administration_install_ansible.md b/docs/src/administration_install_ansible.md index 875dae6a1..bf5e67493 100644 --- a/docs/src/administration_install_ansible.md +++ b/docs/src/administration_install_ansible.md @@ -1,5 +1,7 @@ # Ansible Installation +This is the same as the [Docker installation](administration_install_docker.md), except that Ansible handles all of it automatically. It also does some extra things like setting up TLS and email for your Lemmy instance. + First, you need to [install Ansible on your local computer](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) (e.g. using `sudo apt install ansible`) or the equivalent for you platform. Then run the following commands on your local computer: @@ -11,3 +13,10 @@ cp inventory.example inventory nano inventory # enter your server, domain, contact email ansible-playbook lemmy.yml --become ``` + +To update to a new version, just run the following in your local Lemmy repo: +```bash +git pull origin master +cd ansible +ansible-playbook lemmy.yml --become +``` \ No newline at end of file diff --git a/docs/src/administration_install_docker.md b/docs/src/administration_install_docker.md index 992049839..391299b3d 100644 --- a/docs/src/administration_install_docker.md +++ b/docs/src/administration_install_docker.md @@ -1,29 +1,33 @@ # Docker Installation -Make sure you have both docker and docker-compose(>=`1.24.0`) installed: +Make sure you have both docker and docker-compose(>=`1.24.0`) installed. On Ubuntu, just run `apt install docker-compose docker.io`. Next, ```bash -mkdir lemmy/ -cd lemmy/ +# create a folder for the lemmy files. the location doesnt matter, you can put this anywhere you want +mkdir /lemmy +cd /lemmy +# download default config files wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/prod/docker-compose.yml wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/lemmy.hjson wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/iframely.config.local.js -# Edit lemmy.hjson, and docker-compose.yml to do more configuration (like adding a custom password) docker-compose up -d ``` -and go to http://localhost:8536. +After this, have a look at the [config file](administration_configuration.md) named `lemmy.hjson`, and adjust it, in particular the hostname. -[A sample nginx config](/ansible/templates/nginx.conf) (Note: Avatar / Image uploading won't work without this), could be setup with: +To make Lemmy available outside the server, you need to setup a reverse proxy, like Nginx. [A sample nginx config](/ansible/templates/nginx.conf), could be setup with: ```bash wget https://raw.githubusercontent.com/dessalines/lemmy/master/ansible/templates/nginx.conf # Replace the {{ vars }} sudo mv nginx.conf /etc/nginx/sites-enabled/lemmy.conf ``` + +You will also need to setup TLS, for example with [Let's Encrypt](https://letsencrypt.org/). After this you need to restart Nginx to reload the config. + ## Updating -To update to the newest version, run: +To update to the newest version, you can manually change the version in `docker-compose.yml`. Alternatively, fetch the latest version from our git repo: ```bash wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/prod/docker-compose.yml From d7b730d8e05b76e2f7884266f5ce849c1ce31406 Mon Sep 17 00:00:00 2001 From: Adam Adamsky Date: Wed, 1 Apr 2020 13:15:15 +0000 Subject: [PATCH 10/13] Translated using Weblate (Polish) Currently translated at 100.0% (237 of 237 strings) Translation: Lemmy/lemmy Translate-URL: http://weblate.yerbamate.dev/projects/lemmy/lemmy/pl/ --- ui/translations/pl.json | 256 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 255 insertions(+), 1 deletion(-) diff --git a/ui/translations/pl.json b/ui/translations/pl.json index bfd870e45..9da7dc94a 100644 --- a/ui/translations/pl.json +++ b/ui/translations/pl.json @@ -1,3 +1,257 @@ { + "remove_post": "Usuń Post", + "no_posts": "Brak Postów.", + "create_a_post": "Stwórz post", + "create_post": "Stwórz Post", + "number_of_posts_0": "Post", + "number_of_posts_1": "Posty/ów", + "number_of_posts_2": "Posty/ów", + "posts": "Posty", + "related_posts": "Te posty mogą być powiązane", + "cross_posts": "Ten link został też zapostowany na:", + "comments": "Komentarze", + "number_of_comments_0": "Komentarz", + "number_of_comments_1": "Komentarzy/e", + "number_of_comments_2": "Komentarzy/e", + "post": "post", + "cross_post": "post zewnętrzny", + "cross_posted_to": "post wrzucony na zewnątrz: ", + "remove_comment": "Usuń Komentarz", + "communities": "Społeczności", + "users": "Użytkownicy", + "create_a_community": "Stwórz społeczność", + "create_community": "Stwórz Społeczność", + "remove_community": "Usuń Społeczność", + "subscribed_to_communities": "Subskrybowane <1>społeczności", + "trending_communities": "Popularne <1>społeczności", + "list_of_communities": "Lista społeczności", + "community_reqs": "małe litery, podkreślniki, bez spacji.", + "create_private_message": "Stwórz Prywatną Wiadomość", + "send_secure_message": "Wyślij Bezpieczną Wiadomość", + "send_message": "Wyślij Wiadomość", + "message": "Wiadomość", + "edit": "edytuj", + "reply": "odpowiedz", + "more": "więcej", + "cancel": "Anuluj", + "preview": "Podgląd", + "upload_image": "prześlij obraz", + "avatar": "Awatar", + "upload_avatar": "Prześlij Awatar", + "show_avatars": "Pokaż Awatary", + "formatting_help": "poradnik formatowania", + "lock": "zablokuj", + "messages": "Wiadomości", + "yes": "tak", + "number_of_communities_0": "Społeczność", + "number_of_communities_1": "Społeczności", + "number_of_communities_2": "Społeczności", + "sorting_help": "poradnik sortowania", + "view_source": "pokaż źródło", + "unlock": "odblokuj", + "sticky": "przyklej", + "unsticky": "odklej", + "link": "link", + "archive_link": "link archiwalny", + "mod": "moderator", + "mods": "moderatorzy", + "moderates": "Moderuje", + "settings": "Ustawienia", + "remove_as_mod": "zabierz uprawnienia moderatora", + "appoint_as_mod": "przyznaj uprawnienia moderatora", + "modlog": "Log moderatorski", + "admin": "administrator", + "admins": "administratorzy", + "remove_as_admin": "wycofaj uprawnienia administratora", + "appoint_as_admin": "przyznaj uprawnienia administratora", + "remove": "usuń", + "removed": "usunięte", + "locked": "zablokowane", + "stickied": "przyklejone", + "reason": "Powód", + "mark_as_read": "zaznacz jako przeczytane", + "mark_as_unread": "zaznacz jako nieprzeczytane", + "delete": "usuń", + "deleted": "usunięte", + "delete_account": "Usuń Konto", + "delete_account_confirm": "Ostrzeżenie: twoje dane zostaną bezpowrotnie usunięte. Wpisz swoje hasło aby potwierdzić.", + "restore": "przywróć", + "ban": "zbanuj", + "ban_from_site": "zbanuj ze strony", + "unban": "odbanuj", + "unban_from_site": "odbanuj ze strony", + "banned": "zbanowano", + "save": "zapisz", + "unsave": "cofnij zapis", + "create": "stwórz", + "creator": "autor", + "username": "Nazwa użytkownika", + "email_or_username": "Email lub Nazwa Użytkownika", + "number_of_users_0": "Użytkownik", + "number_of_users_1": "Użytkownicy/ków", + "number_of_users_2": "Użytkownicy/ków", + "number_of_subscribers_0": "Subskrybent", + "number_of_subscribers_1": "Subskrybenci/tów", + "number_of_subscribers_2": "Subskrybenci/tów", + "number_of_points_0": "Punkt", + "number_of_points_1": "Punkty/ów", + "number_of_points_2": "Punkty/ów", + "number_online_0": "Użytkownik Online", + "number_online_1": "Użytkowników Online", + "number_online_2": "Użytkowników Online", + "name": "Nazwa", + "title": "Tytuł", + "category": "Kategoria", + "subscribers": "Subskrybenci", + "both": "Obydwa", + "saved": "Zapisane", + "unsubscribe": "Odsubskrybuj", + "subscribe": "Subskrybuj", + "subscribed": "Zasubskrybowane", + "prev": "Wstecz", + "next": "Dalej", + "sidebar": "Pasek boczny", + "sort_type": "Sortuj typ", + "hot": "Popularne", + "new": "Nowe", + "old": "Stare", + "top_day": "Popularne dzisiaj", + "week": "Tydzień", + "month": "Miesiąc", + "year": "Rok", + "all": "Wszystko", + "top": "Popularne", + "api": "API", + "docs": "Dokumentacja", + "inbox": "Skrzynka odbiorcza", + "inbox_for": "Skrzynka odbiorcza <1>{{user}}", + "mark_all_as_read": "zaznacz wszystko jako przeczytane", + "type": "Rodzaj", + "unread": "Nieprzeczytane", + "replies": "Odpowiedzi", + "mentions": "Wzmianki", + "reply_sent": "Odpowiedź wysłana", + "message_sent": "Wiadomość wysłana", + "search": "Szukaj", + "overview": "Podgląd", + "view": "Widok", + "logout": "Wyloguj", + "login_sign_up": "Zaloguj / Zarejestruj", + "login": "Zaloguj", + "sign_up": "Zarejestruj", + "notifications_error": "Powiadomienia na pulpicie są niedostępne w Twojej przeglądarce. Spróbuj przeglądarkę Firefox lub Chrome.", + "unread_messages": "Nieprzeczytane Wiadomości", + "password": "Hasło", + "verify_password": "Zweryfikuj Hasło", + "old_password": "Stare Hasło", + "forgot_password": "nie pamiętam hasła", + "reset_password_mail_sent": "Wysłano email w celu zresetowania hasła.", + "password_change": "Zmiana Hasła", + "new_password": "Nowe Hasło", + "no_email_setup": "Email nie został poprawnie ustawiony na tym serwerze.", + "email": "Email", + "matrix_user_id": "Użytkownik Matrixa", + "private_message_disclaimer": "Ostrzeżenie: Prywatne wiadomości w Lemmym nie są bezpieczne. Jeśli chcesz wysyłać i odbierać bezpieczne wiadomości załóż konto na <1>Riot.im.", + "send_notifications_to_email": "Wysyłaj powiadomienia na Email", + "optional": "Opcjonalne", + "expires": "Wygasa", + "language": "Język", + "browser_default": "Domyślna wartość przeglądarki", + "downvotes_disabled": "Wdółgłosy wyłączone", + "enable_downvotes": "Włącz Wdółgłosy", + "upvote": "Wgóręgłos", + "number_of_upvotes_0": "Wgóręgłos", + "number_of_upvotes_1": "Wgóręgłosy/ów", + "number_of_upvotes_2": "Wgóręgłosy/ów", + "downvote": "Wdółgłos", + "number_of_downvotes_0": "Wdółgłos", + "number_of_downvotes_1": "Wdółgłosy/ów", + "number_of_downvotes_2": "Wdółgłosy/ów", + "open_registration": "Rejestracja Otwarta", + "registration_closed": "Rejestracja Zamknięta", + "enable_nsfw": "Włącz NSFW", + "url": "URL", + "body": "Treść", + "copy_suggested_title": "skopiuj sugerowany tytuł: {{title}}", + "community": "Społeczność", + "expand_here": "Rozwiń tutaj", + "subscribe_to_communities": "Zasubskrybuj kilka <1>społeczności.", + "chat": "Czat", + "recent_comments": "Najnowsze Komentarze", + "no_results": "Brak wyników.", + "setup": "Instalacja", + "lemmy_instance_setup": "Instalacja Instancji Lemmy", + "setup_admin": "Ustaw Administratora Strony", + "your_site": "twoja witryna", + "modified": "zmodyfikowane", + "nsfw": "NSFW", + "show_nsfw": "Pokaż treści NSFW (+18)", + "theme": "Motyw", + "sponsors": "Sponsorzy", + "sponsors_of_lemmy": "Sponsorzy projektu Lemmy", + "sponsor_message": "Lemmy jest wolnym, <1>otwartoźródłowym oprogramowaniem, co oznacza zero reklam, opłat, czy innych form kapitalizacji, od zawsze na zawsze. Twoje darowizny idą bezpośrednio na rozwój projektu w pełno-etatowym wymiarze. Specjalne wyrazy podziękowania dla następujących osób:", + "support_on_patreon": "Wspieraj w serwisie Patreon", + "support_on_liberapay": "Wspieraj na Liberapay", + "donate_to_lemmy": "Przekaż datek na Lemmiego", + "donate": "Przekaż datek", + "general_sponsors": "Główni Sponsorzy to osoby które wsparły Lemmiego kwotą od $10 do $39.", + "crypto": "Kryptowaluta", + "bitcoin": "Bitcoin", + "ethereum": "Ethereum", + "monero": "Monero", + "code": "Kod", + "joined": "Dołączono", + "by": "przez", + "to": "do", + "from": "od", + "transfer_community": "transfer społeczności", + "transfer_site": "transfer witryny", + "are_you_sure": "na pewno?", + "no": "nie", + "powered_by": "Powered by", + "landing": "Lemmy jest <1>agregatorem linków / alternatywą dla reddita. Jest przeznaczony do działania w ramach cyfrowej przestrzeni nazywanej <2>fediverse<2>. <3>Opiera się na samodzielnym hostingu, posiada aktualizowane na żywo wątki z komentarzami, i zajmuje bardzo mało miejsce (<4>~80kB). Federacja w ramach sieci ActivityPub jest w planach. <5>Ta wersja jest <6>bardzo wczesną wersją beta, co oznacza, że wiele funkcji nadal nie działa tak jak powinny. <7><8>Pod tym adresem można sugerować nową funkcjonalność i zgłaszać błędy.<9>Stworzono z wykorzystaniem <10>Rust, <11>Actix, <12>Inferno, <13>Typescript.", + "not_logged_in": "Nie jesteś zalogowana/y.", + "logged_in": "Zalogowano.", + "community_ban": "Zostałaś/eś zbanowana/y z tej społeczności.", + "site_ban": "Zostałaś/eś zbanowana/y z tej witryny", + "couldnt_create_comment": "Nie udało się stworzyć komentarza.", + "couldnt_like_comment": "Polubienie komentarza nie powiodło się.", + "couldnt_update_comment": "Zaktualizowanie komentarza nie powiodło się.", + "couldnt_save_comment": "Zapisanie komentarza nie powiodło się.", + "couldnt_get_comments": "Pobranie komentarzy nie powiodło się.", + "no_comment_edit_allowed": "Nie masz uprawnień do edycji komentarza.", + "no_post_edit_allowed": "Nie masz uprawnień do edycji posta.", + "no_community_edit_allowed": "Nie masz uprawnień do edycji społeczności.", + "couldnt_find_community": "Nie udało się znaleźć społeczności.", + "couldnt_update_community": "Nie udało się zaktualizować Społeczności.", + "community_already_exists": "Społeczność już istnieje.", + "community_moderator_already_exists": "Moderator społeczności już istnieje.", + "community_follower_already_exists": "Osoba obserwująca społeczność już istnieje.", + "community_user_already_banned": "Użytkownik społeczności jest już zbanowany.", + "couldnt_create_post": "Nie udało się stworzyć posta.", + "post_title_too_long": "Tytuł posta zbyt długi.", + "couldnt_like_post": "Nie udało się polubić posta.", + "couldnt_find_post": "Nie udało się znaleźć posta.", + "couldnt_update_post": "Nie udało się zaktualizować postów", + "couldnt_get_posts": "Nie udało się pobrać postów", + "couldnt_save_post": "Nie udało się zapisać posta.", + "no_slurs": "Bez obelg.", + "not_an_admin": "Nie jest administratorem.", + "site_already_exists": "Witryna już istnieje.", + "couldnt_update_site": "Nie udało się zaktualizować witryny.", + "couldnt_find_that_username_or_email": "Nie udało się znaleźć takiej nazwy użytkownika lub adresu email.", + "password_incorrect": "Hasło niepoprawne.", + "passwords_dont_match": "Hasła nie pasują do siebie.", + "admin_already_created": "Wybacz, funkcja administratora jest już przypisana.", + "user_already_exists": "Użytkownik już istnieje.", + "email_already_exists": "Email już istnieje.", + "couldnt_update_user": "Nie udało się zaktualizować użytkownika.", + "system_err_login": "Błąd systemu. Spróbuj wylogować się i następnie zalogować ponownie.", + "couldnt_create_private_message": "Nie udało się stworzyć prywatnej wiadomości.", + "no_private_message_edit_allowed": "Brak uprawnień do edycji prywatnej wiadomości.", + "couldnt_update_private_message": "Nie udało się zaktualizować prywatnej wiadomości.", + "time": "Czas", + "action": "Akcja", + "block_leaving": "Czy na pewno chcesz wyjść?", + "show_context": "Pokaż kontekst" } - From 0f8be8d6db242342f0deac126118e30d1b181a8c Mon Sep 17 00:00:00 2001 From: olivia maia Date: Wed, 1 Apr 2020 13:15:16 +0000 Subject: [PATCH 11/13] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (237 of 237 strings) Translation: Lemmy/lemmy Translate-URL: http://weblate.yerbamate.dev/projects/lemmy/lemmy/pt_BR/ --- ui/translations/pt_BR.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/translations/pt_BR.json b/ui/translations/pt_BR.json index a9b36b481..c7cce2021 100644 --- a/ui/translations/pt_BR.json +++ b/ui/translations/pt_BR.json @@ -243,5 +243,6 @@ "number_of_upvotes": "{{count}} voto positivo", "number_of_upvotes_plural": "{{count}} votos positivos", "number_of_downvotes": "{{count}} voto negativo", - "number_of_downvotes_plural": "{{count}} votos negativos" + "number_of_downvotes_plural": "{{count}} votos negativos", + "show_context": "Mostrar contexto" } From 0b467cfeed0493a6594d4e1d0457887f81cbe702 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Wed, 1 Apr 2020 11:31:24 -0400 Subject: [PATCH 12/13] Browser notification as plain markdown. Fixes #618 --- ui/src/components/navbar.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/src/components/navbar.tsx b/ui/src/components/navbar.tsx index ea9b619b8..d7f3b5a8a 100644 --- a/ui/src/components/navbar.tsx +++ b/ui/src/components/navbar.tsx @@ -375,12 +375,13 @@ export class Navbar extends Component { let link = isCommentType(reply) ? `/post/${reply.post_id}/comment/${reply.id}` : `/inbox`; - let body = md.render(reply.content); + let htmlBody = md.render(reply.content); + let body = reply.content; // Unfortunately the notifications API can't do html messageToastify( creator_name, creator_avatar, - body, + htmlBody, link, this.context.router ); From 1e0f5cfcea5a467ffed41d4eba722301f22ccf83 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Wed, 1 Apr 2020 13:22:44 -0400 Subject: [PATCH 13/13] Add georgian language for weblate. --- ui/src/utils.ts | 4 ++++ ui/translations/ka.json | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 ui/translations/ka.json diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 48bd175e2..8ecef19b6 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -12,6 +12,7 @@ import 'moment/locale/ca'; import 'moment/locale/fa'; import 'moment/locale/pt-br'; import 'moment/locale/ja'; +import 'moment/locale/ka'; import { UserOperation, @@ -59,6 +60,7 @@ export const languages = [ { code: 'eo', name: 'Esperanto' }, { code: 'es', name: 'Español' }, { code: 'de', name: 'Deutsch' }, + { code: 'ka', name: 'ქართული ენა' }, { code: 'fa', name: 'فارسی' }, { code: 'ja', name: '日本語' }, { code: 'pt_BR', name: 'Português Brasileiro' }, @@ -353,6 +355,8 @@ export function getMomentLanguage(): string { lang = 'pt-br'; } else if (lang.startsWith('ja')) { lang = 'ja'; + } else if (lang.startsWith('ka')) { + lang = 'ka'; } else { lang = 'en'; } diff --git a/ui/translations/ka.json b/ui/translations/ka.json new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/ui/translations/ka.json @@ -0,0 +1,2 @@ +{ +}