summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli.rs43
-rw-r--r--src/configuration.rs107
-rw-r--r--src/gui.rs31
-rw-r--r--src/main.rs115
-rw-r--r--src/middleware.rs108
-rw-r--r--src/model.rs146
-rw-r--r--src/server.rs78
-rw-r--r--src/types/block.rs85
-rw-r--r--src/types/content.rs104
-rw-r--r--src/types/mod.rs5
-rw-r--r--src/types/payload.rs279
-rw-r--r--src/types/util.rs172
-rw-r--r--src/version.rs4
13 files changed, 0 insertions, 1277 deletions
diff --git a/src/cli.rs b/src/cli.rs
deleted file mode 100644
index c91b653..0000000
--- a/src/cli.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use std::path::PathBuf;
-
-use structopt::StructOpt;
-use anyhow::Error;
-
-#[derive(Debug, StructOpt)]
-#[structopt(name = "distrox", about = "Distrox - The distributed social network")]
-pub struct CLI {
- #[structopt(short, long)]
- debug: bool,
-
- #[structopt(short, long)]
- trace: bool,
-
- #[structopt(short, long)]
- port: Option<u16>,
-
- #[structopt(parse(from_os_str))]
- configfile: Option<PathBuf>,
-
- #[structopt(subcommand)]
- cmd: Option<Command>
-}
-
-impl CLI {
- pub fn cmd(&self) -> Option<&Command> {
- self.cmd.as_ref()
- }
-
- pub fn port(&self) -> Option<u16> {
- self.port.as_ref().map(|p| *p)
- }
-}
-
-#[derive(Debug, PartialEq, StructOpt)]
-#[structopt(about = "Start the server part (running in foreground")]
-pub enum Command {
- Server,
-}
-
-pub fn cli() -> Result<CLI, Error> {
- Ok(CLI::from_args())
-}
diff --git a/src/configuration.rs b/src/configuration.rs
deleted file mode 100644
index 5b39090..0000000
--- a/src/configuration.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-use crate::types::util::MimeType;
-
-// use chrono::Duration;
-
-/// Configuration read from a configuration file
-#[derive(Serialize, Deserialize, Debug, AddGetter)]
-pub struct Configuration {
- #[serde(rename = "ipfs-api-url")]
- #[get]
- /// The URL of the API
- api_url: String,
-
- #[serde(rename = "ipfs-api-port")]
- #[get]
- /// The Port of the API
- api_port: u16,
-
- #[serde(rename = "app-port")]
- #[get]
- /// The Port of the App itself
- app_port: u16,
-
- #[serde(rename = "autoserve-chains")]
- #[get]
- /// Whether to automatically "ipfs pin" chain objects
- autoserve_chains: bool,
-
- #[serde(rename = "autoserve-text-posts")]
- #[get]
- /// Whether to automatically "ipfs pin" foreign posts if their content is text
- autoserve_text_posts: bool,
-
- #[serde(rename = "serve-blocked")]
- #[get]
- /// Whether to serve content/chains from blocked profiles
- serve_blocked: bool,
-
- #[serde(rename = "autoserve-followed")]
- #[get]
- /// Whether to automatically "ipfs pin" followed profiles
- autoserve_followed: bool,
-
- #[serde(rename = "max-autoload-per-post")]
- #[get]
- /// Default amount of bytes which are loaded for each post
- max_autoload_per_post: usize,
-
- #[serde(rename = "autoserve-blacklist")]
- #[get]
- /// List of Mimetypes which should not be served
- autoserve_blacklist: Vec<MimeType>,
-
- #[serde(rename = "autoserve-whitelist")]
- #[get]
- /// List of Mimetypes which can be served
- autoserve_whitelist: Vec<MimeType>,
-
- // #[serde(rename = "merge-timeout")]
- // #[get]
- // /// Timeout before merge should be attempted
- // merge_timeout: Duration,
- //
-
- /// Name under which to provide the local device. E.G.
- /// Some("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY")
- ///
- /// If none, one will be generated and set
- #[serde(rename = "device_name")]
- #[get]
- device_name: Option<String>,
-
- /// Key to sign stuff that comes from this device.
- ///
- /// Create by using `ipfs key gen <name>`
- #[serde(rename = "device_key")]
- #[get]
- device_key: Option<String>,
-
- /// Devices for the profile
- /// E.G:
- /// ["/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"]
- #[serde(rename = "devices")]
- #[get]
- devices: Vec<String>,
-}
-
-impl Default for Configuration {
- fn default() -> Self {
- Configuration {
- api_url : String::from("127.0.0.1"),
- api_port : 5001,
- app_port : 5002,
- autoserve_chains : true,
- autoserve_text_posts : true,
- serve_blocked : false,
- autoserve_followed : true,
- max_autoload_per_post : 1024 * 1024,
- autoserve_blacklist : Vec::new(),
- autoserve_whitelist : Vec::new(),
- // merge_timeout : Duration::minutes(15),
- device_name : None,
- device_key : None,
- devices : Vec::new(),
- }
- }
-}
-
diff --git a/src/gui.rs b/src/gui.rs
deleted file mode 100644
index 1d5281e..0000000
--- a/src/gui.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use std::fmt::Debug;
-
-use anyhow::Error;
-use anyhow::Result;
-use web_view::WVResult;
-use web_view::WebView;
-
-use crate::cli::*;
-use crate::types::util::*;
-
-pub fn run_gui(adr: String) -> Result<()> {
- let webview_content = web_view::Content::Url(format!("http://{}", adr));
-
- web_view::builder()
- .title("My Project")
- .content(webview_content)
- .resizable(true)
- .debug(true)
- .user_data(())
- .invoke_handler(invoke_handler)
- .build()
- .map_err(Error::from)?
- .run()
- .map_err(Error::from)
-}
-
-fn invoke_handler<T: Debug>(webview: &mut WebView<T>, s: &str) -> WVResult {
- debug!("invoke-handler: {:?}, {:?}", webview, s);
- Ok(())
-}
-
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index 80e6ec9..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-#![allow(warnings)]
-
-extern crate ipfs_api;
-extern crate chrono;
-extern crate mime;
-extern crate futures;
-extern crate serde;
-extern crate serde_json;
-extern crate uuid;
-extern crate clap;
-extern crate toml;
-extern crate config;
-extern crate hyper;
-extern crate env_logger;
-extern crate itertools;
-extern crate xdg;
-extern crate handlebars;
-extern crate web_view;
-extern crate actix_rt;
-extern crate actix_web;
-extern crate failure;
-extern crate pidlock;
-
-#[macro_use] extern crate anyhow;
-#[macro_use] extern crate is_match;
-#[macro_use] extern crate serde_derive;
-#[macro_use] extern crate log;
-#[macro_use] extern crate tokio;
-#[macro_use] extern crate add_getters_setters;
-#[macro_use] extern crate structopt;
-
-mod cli;
-mod configuration;
-mod gui;
-mod model;
-mod middleware;
-mod server;
-mod types;
-mod version;
-
-use std::collections::BTreeMap;
-use std::str::FromStr;
-use std::ops::Deref;
-use std::sync::Arc;
-use std::path::PathBuf;
-
-use chrono::NaiveDateTime;
-use futures::future::Future;
-use futures::future::FutureExt;
-use futures::future::TryFutureExt;
-use serde_json::to_string_pretty as serde_json_to_string_pretty;
-use serde_json::from_str as serde_json_from_str;
-use anyhow::Result;
-use anyhow::Error;
-use env_logger::Env;
-
-use crate::cli::*;
-use crate::configuration::Configuration;
-use crate::model::Model;
-use crate::middleware::Middleware;
-use crate::types::block::Block;
-use crate::types::content::Content;
-use crate::types::payload::Payload;
-use crate::types::util::IPFSHash;
-use crate::types::util::IPNSHash;
-use crate::types::util::MimeType;
-use crate::types::util::Timestamp;
-use crate::types::util::Version;
-
-use std::process::exit;
-
-#[actix_rt::main]
-async fn main() -> Result<()> {
- let cli = cli()?;
- let _ = env_logger::from_env(Env::default().default_filter_or("info")).init();
- debug!("Logger initialized");
-
- let config_file_name = PathBuf::from("distrox.toml");
- let config: Configuration = {
- let configfile = xdg::BaseDirectories::with_prefix("distrox")?
- .find_config_file(&config_file_name)
- .ok_or_else(|| anyhow!("No configuration found"))?;
-
- let configstr = ::std::fs::read_to_string(&configfile)?;
- ::toml::from_str(&configstr)?
- };
-
- let port = cli.port().unwrap_or_else(|| *config.get_app_port());
- let adr = format!("127.0.0.1:{}", port);
-
- let mut server_lock = crate::server::mk_lock();
- let server_running = crate::server::is_running(&server_lock);
- let start_server = crate::server::do_start(&cli);
-
- match (server_running, start_server) {
- (true, false) => crate::gui::run_gui(adr),
- (false, false) => {
- // fork()
- info!("Spawning server thread...");
- let path = std::env::current_exe()?;
- let mut child = std::process::Command::new(path).arg("server").spawn()?;
- let r = crate::gui::run_gui(adr);
- child.kill()?;
- r
- },
-
- (false, true) => crate::server::run_server(config, server_lock, adr).await,
-
- (true, true) => {
- info!("Server is already running. Doing nothing.");
- return Ok(())
- },
- }
-}
-
diff --git a/src/middleware.rs b/src/middleware.rs
deleted file mode 100644
index 61fe716..0000000
--- a/src/middleware.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-use std::collections::BTreeMap;
-
-use anyhow::Error;
-use futures::Stream;
-use futures::stream;
-
-use crate::types::util::IPFSHash;
-use crate::types::util::MimeType;
-use crate::types::util::IPNSHash;
-use crate::types::block::Block;
-use crate::model::Model;
-use crate::types::content::Content;
-use crate::types::payload::Payload;
-use crate::types::util::Timestamp;
-use crate::version::protocol_version;
-
-/// The "Middleware" type implements the actual application logic
-#[derive(Debug, Clone)]
-pub struct Middleware {
- repo: Model,
- device_name: IPNSHash,
- publishing_key: String
-}
-
-impl Middleware {
-
- pub fn load(device_name: IPNSHash, publishing_key: String, host: &str, port: u16) -> Result<Self, Error> {
- Model::new(host, port).map(|repo| Middleware { repo, device_name, publishing_key })
- }
-
- pub async fn new_profile(repo: Model, publishing_key: &str, names: Vec<String>) -> Result<Self, Error> {
- let payload = Payload::Profile {
- names,
- picture: None,
- more: BTreeMap::new(),
- };
- let timestamp = Timestamp::now();
- let content = Content::new(vec![], Some(timestamp), payload);
-
- let content_hash = repo.put_content(content).await?;
- let head = repo.put_block(Block::new(protocol_version(), vec![], content_hash)).await?;
- let device_name = repo.publish(&publishing_key, &head).await?;
-
- Ok(Middleware { repo, device_name, publishing_key: publishing_key.to_string() })
- }
-
- pub async fn new_post(&self,
- content: Vec<u8>,
- mime: MimeType,
- reply_to: Option<IPFSHash>,
- comments_will_be_propagated: Option<bool>,
- comments_propagated_until: Option<Timestamp>)
- -> Result<(), Error>
- {
- let content_hash = self.repo.put_raw_bytes(content).await?;
-
- let payload = Payload::Post {
- content_format: mime,
- content: content_hash,
- reply_to,
- comments_will_be_propagated,
- comments_propagated_until,
- };
- let timestamp = Timestamp::now();
- let content = Content::new(vec![], Some(timestamp), payload);
-
- let content_hash = self.repo.put_content(content).await?;
-
- let head = self.repo.put_block(Block::new(protocol_version(), vec![], content_hash)).await?;
- let device_name = self.repo.publish(&self.publishing_key, &head).await?;
-
- Ok(())
- }
-
- pub fn blocks(&self, head: IPFSHash) -> impl Stream<Item = Result<Block, Error>> {
- stream::unfold((self.repo.clone(), vec![head]), move |(repo, mut state)| {
- async {
- if let Some(hash) = state.pop() {
- match repo
- .get_block(hash)
- .await
- .map(move |block| {
- block.parents().iter().for_each(|parent| {
- state.push(parent.clone())
- });
-
- (block, state)
- })
- .map(Some)
- .transpose()
- {
- Some(Ok((item, state))) => Some((Ok(item), (repo, state))),
- Some(Err(e)) => Some((Err(e), (repo, vec![]))),
- None => None,
- }
- } else {
- None
- }
- }
- })
- }
-
- pub async fn blocks_of(&self, ipns: IPNSHash) -> Result<impl Stream<Item = Result<Block, Error>>, Error> {
- self.repo.resolve(ipns).await.map(|ipfs| self.blocks(ipfs))
- }
-
-}
-
diff --git a/src/model.rs b/src/model.rs
deleted file mode 100644
index 85fcf22..0000000
--- a/src/model.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-//! The "model" module implements the Database-layer of the application
-
-use std::io::Cursor;
-use std::ops::Deref;
-use std::result::Result as RResult;
-use std::sync::Arc;
-
-use anyhow::Error;
-use chrono::NaiveDateTime;
-use failure::Fail;
-use futures::future::Future;
-use futures::future::FutureExt;
-use futures::stream::Stream;
-use futures::stream::StreamExt;
-use futures::stream::TryStreamExt;
-use ipfs_api::IpfsClient;
-use ipfs_api::TryFromUri;
-use serde::Serialize;
-use serde::de::DeserializeOwned;
-use serde_json::from_str as serde_json_from_str;
-use serde_json::to_string as serde_json_to_str;
-
-use crate::types::block::Block;
-use crate::types::content::Content;
-use crate::types::payload::Payload;
-use crate::types::util::IPFSHash;
-use crate::types::util::IPNSHash;
-
-#[derive(Clone)]
-pub struct Model(IpfsClient);
-
-impl std::fmt::Debug for Model{
- fn fmt(&self, f: &mut std::fmt::Formatter) -> RResult<(), std::fmt::Error> {
- write!(f, "Model")
- }
-}
-
-impl Model {
- pub fn new(host: &str, port: u16) -> Result<Model, Error> {
- debug!("Creating new Model object: {}:{}", host, port);
- IpfsClient::from_str(&format!("{}:{}", host, port))
- .map(Model)
- .map_err(|e| Error::from(e.compat()))
- }
-
-
- //
- //
- // Low-level interface to the ipfs-api
- //
- //
-
- pub(crate) async fn get_raw_bytes<H: AsRef<IPFSHash>>(&self, hash: H) -> Result<Vec<u8>, Error> {
- debug!("Get: {}", hash.as_ref());
- self.0
- .cat(hash.as_ref())
- .map_ok(|b| b.to_vec())
- .try_concat()
- .map(|r| r.map_err(|e| anyhow!("UNIMPLEMENTED!()")))
- .await
- }
-
- pub(crate) async fn put_raw_bytes(&self, data: Vec<u8>) -> Result<IPFSHash, Error> {
- debug!("Put: {:?}", data);
- self.0
- .add(Cursor::new(data))
- .await
- .map(|res| IPFSHash::from(res.hash))
- .map_err(|e| anyhow!("UNIMPLEMENTED!()"))
- }
-
- pub(crate) async fn publish(&self, key: &str, hash: &str) -> Result<IPNSHash, Error> {
- debug!("Publish: {:?} -> {:?}", key, hash);
- self.0
- .name_publish(hash, false, None, None, Some(key))
- .await
- .map(|res| IPNSHash::from(res.value))
- .map_err(|e| anyhow!("UNIMPLEMENTED!()"))
- }
-
- pub(crate) async fn resolve(&self, ipns: IPNSHash) -> Result<IPFSHash, Error> {
- self.0
- .name_resolve(Some(&ipns), true, false)
- .await
- .map(|res| IPFSHash::from(res.path))
- .map_err(|e| anyhow!("UNIMPLEMENTED!()"))
- }
-
- //
- //
- // Generic typed interface
- //
- //
-
- pub(crate) async fn get_typed<H, D>(&self, hash: H) -> Result<D, Error>
- where H: AsRef<IPFSHash>,
- D: DeserializeOwned
- {
- self.get_raw_bytes(hash)
- .await
- .and_then(|data| {
- debug!("Got data, building object: {:?}", data);
-
- serde_json::from_slice(&data).map_err(|e| Error::from(e.compat()))
- })
- }
-
- pub(crate) async fn put_typed<S, Ser>(&self, data: &S) -> Result<IPFSHash, Error>
- where S: AsRef<Ser>,
- Ser: Serialize
- {
- let data = serde_json_to_str(data.as_ref())?;
- self.put_raw_bytes(data.into_bytes()).await
- }
-
- //
- //
- // Typed interface
- //
- //
-
- pub async fn get_block<H>(&self, hash: H) -> Result<Block, Error>
- where H: AsRef<IPFSHash>
- {
- self.get_typed(hash).await
- }
-
- pub async fn put_block<B>(&self, b: B) -> Result<IPFSHash, Error>
- where B: AsRef<Block>
- {
- self.put_typed(b.as_ref()).await
- }
-
- pub async fn get_content<H>(&self, hash: H) -> Result<Content, Error>
- where H: AsRef<IPFSHash>
- {
- self.get_typed(hash).await
- }
-
- pub async fn put_content<C>(&self, c: C) -> Result<IPFSHash, Error>
- where C: AsRef<Content>
- {
- self.put_typed(c.as_ref()).await
- }
-
-}
diff --git a/src/server.rs b/src/server.rs
deleted file mode 100644
index b1fa237..0000000
--- a/src/server.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-use std::path::PathBuf;
-
-use anyhow::Error;
-use anyhow::Result;
-use pidlock::{Pidlock, PidlockState};
-use actix_web::HttpResponse;
-use actix_web::Responder;
-use actix_web::http::StatusCode;
-use actix_web::body::Body;
-
-use crate::cli::*;
-use crate::configuration::Configuration;
-use crate::middleware::Middleware;
-use crate::types::util::*;
-
-pub fn mk_lock() -> Pidlock {
- pidlock::Pidlock::new("/tmp/distrox_server.pid")
-}
-
-pub fn do_start(cli: &CLI) -> bool {
- cli.cmd().map(|cmd| Command::Server == *cmd).unwrap_or(false)
-}
-
-pub fn is_running(server_lock: &Pidlock) -> bool {
- PathBuf::from("/tmp/distrox_server.pid").exists()
-}
-
-
-pub async fn run_server(config: Configuration, mut server_lock: Pidlock, adr: String) -> Result<()> {
- let app = {
- let device_name = config.get_device_name();
- let device_key = config.get_device_key();
-
- if let (Some(name), Some(key)) = (device_name, device_key) {
- let name = IPNSHash::from(name.clone());
- let key = key.clone();
- let api_url = config.get_api_url().clone();
- let api_port = config.get_api_port().clone();
-
- Middleware::load(name, key, &api_url, api_port)
- } else {
- // ask user for name(s)
- // boot repository
- // load Middleware object
- unimplemented!()
- }
- }?;
-
- info!("Starting server");
- let _ = server_lock.acquire().map_err(|_| anyhow!("Error while getting the PID lock"))?;
-
- info!("Got PID lock for server");
- actix_web::HttpServer::new(|| {
- actix_web::App::new()
- .route("*", actix_web::web::get().to(index))
- })
- .bind(adr.clone())
- .expect(&format!("Could not bind to address {}", adr))
- .run()
- .await;
-
- info!("Server shutdown");
- info!("Releasing PID lock for server");
- server_lock.release().map_err(|_| anyhow!("Error while releasing the PID lock"))
-}
-
-async fn index() -> impl Responder {
- debug!("serve index");
- let s = format!("{pre}{style}{index}{post}",
- pre = include_str!("../assets/index_pre.html"),
- style = include_str!("../assets/style.css"),
- index = include_str!("../assets/index.html"),
- post = include_str!("../assets/index_post.html"),
- );
-
- HttpResponse::build(StatusCode::OK).body(Body::from_slice(s.as_bytes()))
-}
-
diff --git a/src/types/block.rs b/src/types/block.rs
deleted file mode 100644
index c70ceef..0000000
--- a/src/types/block.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-use crate::types::util::IPFSHash;
-use crate::types::util::Version;
-use crate::types::content::Content;
-use crate::types::payload::*;
-use crate::types::content::LoadedContent;
-use crate::model::Model;
-
-use anyhow::Error;
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct Block {
- /// The version of the API in use
- #[serde(rename = "v")]
- version: Version,
-
- /// The parents of this Profile instance
- ///
- /// Multiple are required for merging.
- #[serde(rename = "parents")]
- #[serde(default)]
- parents: Vec<IPFSHash>,
-
- /// The content of this block, pointed to by IPFS hash.
- #[serde(rename = "content")]
- content: IPFSHash,
-}
-
-impl Block {
- pub fn new(version: Version, parents: Vec<IPFSHash>, content: IPFSHash) -> Self {
- Block { version, parents, content }
- }
-
- pub fn version(&self) -> &Version {
- &self.version
- }
-
- pub fn parents(&self) -> &Vec<IPFSHash> {
- &self.parents
- }
-
- pub fn content(&self) -> &IPFSHash {
- &self.content
- }
-
- pub async fn load(self, r: &Model) -> Result<LoadedBlock, Error> {
- Ok({
- LoadedBlock {
- version: self.version,
- parents: self.parents,
- content: r.get_content(&self.content)
- .await?
- .load(r)
- .await?
- }
- })
- }
-}
-
-impl AsRef<Block> for Block {
- fn as_ref(&self) -> &Self {
- &self
- }
-}
-
-#[derive(Debug)]
-pub struct LoadedBlock {
- version: Version,
- parents: Vec<IPFSHash>,
- content: LoadedContent,
-}
-
-impl LoadedBlock {
- pub fn version(&self) -> &Version {
- &self.version
- }
-
- pub fn parents(&self) -> &Vec<IPFSHash> {
- &self.parents
- }
-
- pub fn content(&self) -> &LoadedContent {
- &self.content
- }
-}
-
diff --git a/src/types/content.rs b/src/types/content.rs
deleted file mode 100644
index 8b6eb4d..0000000
--- a/src/types/content.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-use std::collections::BTreeMap;
-
-use anyhow::Error;
-
-use crate::types::util::IPFSHash;
-use crate::types::util::IPNSHash;
-use crate::types::util::MimeType;
-use crate::types::util::Timestamp;
-use crate::types::payload::Payload;
-use crate::types::payload::LoadedPayload;
-use crate::model::Model;
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct Content {
-
- //
- //
- // Metadata about the content
- // --------------------------
- //
- // This metadata should be added to each block version. It is a small amount of bytes, but it
- // makes the aggregation much simpler.
- //
- // In v2 of the API, we might change this and put all this meta-information into variants of
- // `Payload`, if we find that aggregation is fast enough.
- //
-
- /// A list of IPNS hashes which are posting to this chain (so if a client has one profile
- /// node, it can find the latest profile nodes from all devices a user posts from)
- #[serde(rename = "devices")]
- devices: Vec<IPNSHash>,
-
- /// Timestamp (UNIX timestamp) when this was created. Can be left out.
- #[serde(rename = "timestamp")]
- #[serde(default)]
- timestamp: Option<Timestamp>,
-
- /// The payload of the content block
- #[serde(rename = "payload")]
- payload: Payload,
-
-}
-
-impl Content {
-
- pub fn new(devices: Vec<IPNSHash>, timestamp: Option<Timestamp>, payload: Payload) -> Content {
- Content { devices, timestamp, payload }
- }
-
- pub fn devices(&self) -> &Vec<IPNSHash> {
- &self.devices
- }
-
- pub fn timestamp(&self) -> Option<&Timestamp> {
- self.timestamp.as_ref()
- }
-
- pub fn payload(&self) -> &Payload {
- &self.payload
- }
-
- pub(crate) fn push_device(&mut self, dev: IPNSHash) {
- self.devices.push(dev);
- }
-
- pub async fn load(self, r: &Model) -> Result<LoadedContent, Error> {
- Ok({
- LoadedContent {
- devices: self.devices,
- timestamp: self.timestamp,
- payload: self.payload.load(r).await?
- }
- })
- }
-
-}
-
-impl AsRef<Content> for Content {
- fn as_ref(&self) -> &Self {
- &self
- }
-}
-
-#[derive(Debug)]
-pub struct LoadedContent {
- devices: Vec<IPNSHash>,
- timestamp: Option<Timestamp>,
- payload: LoadedPayload,
-}
-
-impl LoadedContent {
- pub fn devices(&self) -> &Vec<IPNSHash> {
- &self.devices
- }
-
- pub fn timestamp(&self) -> Option<&Timestamp> {
- self.timestamp.as_ref()
- }
-
- pub fn payload(&self) -> &LoadedPayload {
- &self.payload
- }
-}
-
diff --git a/src/types/mod.rs b/src/types/mod.rs
deleted file mode 100644
index 06ac03a..0000000
--- a/src/types/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-pub mod block;
-pub mod content;
-pub mod payload;
-pub mod util;
-
diff --git a/src/types/payload.rs b/src/types/payload.rs
deleted file mode 100644
index 47f28a6..0000000
--- a/src/types/payload.rs
+++ /dev/null
@@ -1,279 +0,0 @@
-use std::collections::BTreeMap;
-
-use anyhow::Error;
-
-use crate::types::util::IPFSHash;
-use crate::types::util::IPNSHash;
-use crate::types::util::MimeType;
-use crate::types::util::Timestamp;
-use crate::model::Model;
-
-
-/// The Payload type represents the Payload of a Content object
-///
-/// The Payload type contains several variants, as an update (new block) may be either just a
-/// metadata update (like a merge) or something more meaningful.
-///
-/// For example, the payload might be a `Payload::Post`, Alice has posted new kitten pictures!
-/// Or a `Payload::ProfileUpdate` which contains information about Alice herself
-///
-#[derive(Serialize, Deserialize, Debug)]
-#[serde(tag = "payload_type")]
-pub enum Payload {
-
- /// A variant that represents no payload
- ///
- /// This normally happens when merging two chains.
- None,
-
- /// A post
- ///
- /// A post can be anything which contains data. The data itself is put behind an IPFS hash, the
- /// Payload::Post only contains meta-information like payload size, content format (MIME) and
- /// optionally a list of IPFS hashes which are related to the post itself.
- Post {
- /// Format of the actual content
- #[serde(rename = "content-format")]
- content_format: MimeType,
-
- /// IPFS hash pointing to the actual content
- #[serde(rename = "content")]
- content: IPFSHash,
-
- /// If this post is a reply to another post, this field can be used to point to the
- /// replied-to post.
- #[serde(rename = "reply-to")]
- #[serde(default)]
- reply_to: Option<IPFSHash>,
-
- //
- //
- // Metadata for the post which should be visible to others
- //
- //
-
- /// A flag whether comments to this post will be propagated
- ///
- /// From a technical POV, comments can be done anyways, but the client which published the
- /// comment has to "accept" comments (via `PostComments`) to make them visible to others.
- /// This flag indicates whether the client will do that (either manually or automatically,
- /// which is not indicated here).
- ///
- /// # Available values
- ///
- /// A value of `Some(false)` means that comments will not be propagated, so others will not
- /// see them. A UI may not show "add comment"-buttons if this is set to `Some(false)`.
- ///
- /// A value of `Some(true)` means that comments will eventually be propagated. This means
- /// that the author might accept them by hand or tell their client to automatically accept
- /// all comments. This distinction is client-side implementation specific.
- ///
- /// A value of `None` indicates no setting here, which means that the client might or might
- /// not propagate any comments.
- #[serde(rename = "comments-will-be-propagated")]
- #[serde(default)]
- comments_will_be_propagated: Option<bool>,
-
- /// A value which describes until what date/time comments will be propagated
- ///
- /// This is a hint for other users whether comments will be propagated or not.
- /// A UI might not show a "Reply" button after that date.
- #[serde(rename = "comments-propagated-until")]
- #[serde(default)]
- comments_propagated_until: Option<Timestamp>,
- },
-
- /// Comments for a post
- ///
- /// Propagating answers to a post must be done by the author of the post itself.
- /// This variant is for publishing a message "These are the comments on my post <hash>".
- ///
- /// Always all comments should be published, not just the new ones!
- AttachedPostComments {
- /// The Hash of the Block for the Post which the comments are for
- #[serde(rename = "comments-for")]
- comments_for: IPFSHash,
-
- /// Hashes of direct answers to the post pointed to by "comments_for"
- /// This list always represents a full list of all answers. As comments are added, old
- /// versions of this object should be ignored by clients if newer variants for the same `comments_for`-object are published.
- #[serde(rename = "refs")]
- #[serde(default)]
- refs: Vec<IPFSHash>,
- },
-
- /// A variant describing a profile
- ///
- /// A profile contains the whole set of data which is considered "current" for the
- /// profile. Older versions of this shall then be ignored by clients.
- Profile {
-
- /// The self-assigned names of a user.
- #[serde(rename = "names")]
- names: Vec<String>,
-
- /// An optional user profile picture
- ///
- /// The picture itself is located behind a IPFS hash. If the hash does not resolve to a
- /// picture, clients should ignore it.
- ///
- /// A profile may only contain _one_ profile picture in the current version of the
- /// protocol.
- #[serde(rename = "picture")]
- #[serde(default)]
- picture: Option<IPFSHash>,
-
- /// A "more" field where arbitrary data can be stored. Like "Biography", "Hobbies",
- /// "Political opinion" or even pictures, ...
- ///
- /// The stored data can be of any type.
- #[serde(rename = "user-defined")]
- #[serde(default)]
- more: BTreeMap<String, Userdata>,
- },
-}
-
-impl Payload {
- /// Helper function
- pub fn is_none(&self) -> bool {
- match self {
- &Payload::None => true,
- _ => false,
- }
- }
-
- /// Helper function
- pub fn is_post(&self) -> bool {
- match self {
- &Payload::Post {..} => true,
- _ => false,
- }
- }
-
- /// Helper function
- pub fn is_attached_post_comments(&self) -> bool {
- match self {
- &Payload::AttachedPostComments {..} => true,
- _ => false,
- }
- }
-
- /// Helper function
- pub fn is_profile(&self) -> bool {
- match self {
- &Payload::Profile {..} => true,
- _ => false,
- }
- }
-
- pub async fn load(self, r: &Model) -> Result<LoadedPayload, Error> {
- match self {
- Payload::None => Ok(LoadedPayload::None),
- Payload::Post {
- content_format,
-