Skip to content

Commit

Permalink
0.12.0: Restore minds API
Browse files Browse the repository at this point in the history
  • Loading branch information
DoumanAsh committed Mar 8, 2019
1 parent 1775c03 commit e4c5a4c
Show file tree
Hide file tree
Showing 12 changed files with 343 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fie"
version = "0.11.0"
version = "0.12.0"
authors = ["Douman <douman@gmx.se>"]
repository = "https://github.com/DoumanAsh/fie"
description = "Small and cute social media utility."
Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@
[![Build status](https://ci.appveyor.com/api/projects/status/oc937oppd38x1y4y/branch/master?svg=true)](https://ci.appveyor.com/project/DoumanAsh/fie/branch/master)
[![Build Status](https://travis-ci.org/DoumanAsh/fie.svg?branch=master)](https://travis-ci.org/DoumanAsh/fie)
[![Crates.io](https://img.shields.io/crates/v/fie.svg)](https://crates.io/crates/fie)
[![Dependency status](https://deps.rs/crate/fie/0.11.0/status.svg)](https://deps.rs/crate/fie)
[![Dependency status](https://deps.rs/crate/fie/0.12.0/status.svg)](https://deps.rs/crate/fie)

Small and cute social media CLI.

![Icon](icon.jpg)

## Download links

* Windows [32bit](https://github.com/DoumanAsh/fie/releases/download/0.11.0/fie-0.11.0-i686-pc-windows-msvc.zip)
* Windows [64bit](https://github.com/DoumanAsh/fie/releases/download/0.11.0/fie-0.11.0-x86_64-pc-windows-msvc.zip)
* Linux [64bit](https://github.com/DoumanAsh/fie/releases/download/0.11.0/fie-0.11.0-x86_64-unknown-linux-gnu.zip)
* OSX [64bit](https://github.com/DoumanAsh/fie/releases/download/0.11.0/fie-0.11.0-x86_64-apple-darwin.zip)
* Windows [32bit](https://github.com/DoumanAsh/fie/releases/download/0.12.0/fie-0.12.0-i686-pc-windows-msvc.zip)
* Windows [64bit](https://github.com/DoumanAsh/fie/releases/download/0.12.0/fie-0.12.0-x86_64-pc-windows-msvc.zip)
* Linux [64bit](https://github.com/DoumanAsh/fie/releases/download/0.12.0/fie-0.12.0-x86_64-unknown-linux-gnu.zip)
* OSX [64bit](https://github.com/DoumanAsh/fie/releases/download/0.12.0/fie-0.12.0-x86_64-apple-darwin.zip)

## Supported social platforms:

* Gab (through unofficial API so may break);
* Twitter. Using official API.
* Gab (through unofficial API so may break);
* Mastodon. Using official API.
* Minds. Using semi-official API.

## Configuration

Expand All @@ -42,6 +43,7 @@ FLAGS:
-g, --gab Use gab.ai. By default all social medias are used unless flag is specified.
-h, --help Prints help information
-m, --mastodon Use mastodon. By default all social medias are used unless flag is specified.
--minds Use minds. By default all social medias are used unless flag is specified.
-t, --twitter Use twitter. By default all social medias are used unless flag is specified.
-V, --version Prints version information
Expand Down
18 changes: 14 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@ If both are missing then error happens
Just provide your password and login

```toml
[gab]
[api.gab]
username = "username"
password = "password"
```

## Minds

Just provide your password and login

```toml
[api.gab]
username = "username"
password = "password"
```
Expand All @@ -30,7 +40,7 @@ After that go to section `Keys and Access Tokens` to retrieve configuration:
Put it in section below:

```toml
[twitter.consumer]
[api.twitter.consumer]
key = "key"
secret = "secret"
```
Expand All @@ -39,7 +49,7 @@ secret = "secret"
Put it in section below:

```toml
[twitter.access]
[api.twitter.access]
key = "token"
secret = "secret"
```
Expand All @@ -53,7 +63,7 @@ You need to provide host name of the Mastodon instance.
Access token can be granted by creating own application via `Preferences->Developement->New Application`

```toml
[mastodon]
[api.mastodon]
host = "pawoo.net"
access_token = ""
```
7 changes: 6 additions & 1 deletion fie.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Login and password from Gab.ai
# Login and password from Gab.com
[api.gab]
username = "username"
password = "password"

# Login and password from Minds.com
[api.minds]
username = "username"
password = "password"

# Consumer Token of twitter app
[api.twitter.consumer]
key = "key"
Expand Down
5 changes: 4 additions & 1 deletion src/cli/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl Args {
let args = Self::from_args();

//Unless user specifies manually, we use configuration defaults
if args.flags.twitter || args.flags.gab || args.flags.mastodon {
if args.flags.twitter || args.flags.gab || args.flags.mastodon || args.flags.minds {
*platforms = unsafe { mem::transmute(args.flags) }
}

Expand All @@ -40,6 +40,9 @@ pub struct Flags {
#[structopt(short = "m", long = "mastodon")]
///Use mastodon. By default all social medias are used unless flag is specified.
pub mastodon: bool,
#[structopt(long = "minds")]
///Use minds. By default all social medias are used unless flag is specified.
pub minds: bool,
}

#[derive(Debug, StructOpt)]
Expand Down
11 changes: 10 additions & 1 deletion src/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,22 @@ fn create_api(config: Config) -> io::Result<fie::API> {
}
}

if config.platforms.minds {
if let Err(error) = api.enable(config.api.minds) {
eprintln!("{}", error);
} else {
any_enabled = true
}
}

match any_enabled {
true => Ok(api),
false => Err(io::Error::new(io::ErrorKind::Other, "No API is enabled :(")),
}
}

fn handle_post_result(result: fie::api::PostResult) {
let (twitter, gab, mastodon) = result.into_parts();
let (twitter, gab, mastodon, minds) = result.into_parts();

let handle_inner = |prefix, result| if let Some(result) = result {
match result {
Expand All @@ -56,6 +64,7 @@ fn handle_post_result(result: fie::api::PostResult) {
handle_inner("Twitter", twitter);
handle_inner("Gab", gab);
handle_inner("Mastodon", mastodon);
handle_inner("Minds", minds);
}

fn open_batch(path: &str) -> io::Result<Vec<fie::data::Post>> {
Expand Down
22 changes: 11 additions & 11 deletions src/lib/api/gab/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ impl Gab {
// For image we wait twice of time
// just to be sure
req.or_else(|resp| resp.retry(http::get_timeout()).into_future().flatten())
.map_err(|_| GabError::ImageUploadSendError)
.and_then(|resp| match resp.is_success() {
true => Ok(resp),
false => Err(GabError::ImageUploadServerReject),
}).and_then(|response| response.json::<UploadResponse>().map_err(|_| GabError::PostUploadInvalidResponse))
.map(|response| response.id)
.map_err(|_| GabError::ImageUploadSendError)
.and_then(|resp| match resp.is_success() {
true => Ok(resp),
false => Err(GabError::ImageUploadServerReject),
}).and_then(|response| response.json::<UploadResponse>().map_err(|_| GabError::PostUploadInvalidResponse))
.map(|response| response.id)
}

///Prepares post upload request.
Expand All @@ -142,10 +142,10 @@ impl Gab {
.send();

req.map_err(|_| GabError::PostUploadSendError)
.and_then(|resp| match resp.is_success() {
true => Ok(resp),
false => Err(GabError::PostUploadServerReject),
}).and_then(|resp| resp.json::<PostResponse>().map_err(|_| GabError::PostUploadInvalidResponse))
.map(|resp| resp.post.id.into())
.and_then(|resp| match resp.is_success() {
true => Ok(resp),
false => Err(GabError::PostUploadServerReject),
}).and_then(|resp| resp.json::<PostResponse>().map_err(|_| GabError::PostUploadInvalidResponse))
.map(|resp| resp.post.id.into())
}
}
78 changes: 78 additions & 0 deletions src/lib/api/minds/data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//!Minds data

use serde_derive::{Serialize, Deserialize};

use crate::data::PostFlags;

///Auth payload
#[derive(Serialize, Debug)]
pub struct Auth<'a> {
grant_type: &'static str,
client_id: &'static str,
username: &'a str,
password: &'a str,
}

impl<'a> Auth<'a> {
///Creates new payload
pub fn new(username: &'a str, password: &'a str) -> Self {
Auth {
grant_type: "password",
client_id: "mobile",
username,
password,
}
}
}

///Payload for successful authorization
#[derive(Deserialize, Debug)]
pub struct Oauth2 {
///Access token
pub access_token: String,
///Expiration time(units?)
pub expires_in: u64,
///Request's textual status
pub status: String,
}

///Payload for post
#[derive(Serialize, Debug)]
pub struct Post<'a> {
wire_threshold: Option<String>,
message: &'a str,
is_rich: u8,
title: Option<String>,
description: Option<String>,
thumbnail: Option<String>,
url: Option<String>,
attachment_guid: &'a Option<String>,
///Whether content is safe for work or not
pub mature: u8,
access_id: u8,
}

impl<'a> Post<'a> {
///Creates new post
pub fn new(message: &'a str, attachment_guid: &'a Option<String>, flags: &PostFlags) -> Self {
Post {
wire_threshold: None,
message,
is_rich: 0,
title: None,
description: None,
thumbnail: None,
url: None,
attachment_guid,
mature: flags.nsfw as u8,
access_id: 2,
}
}
}

///Response to successful upload/post
#[derive(Deserialize, Debug)]
pub struct UploadResponse {
///Newly created entity ID
pub guid: String,
}
47 changes: 47 additions & 0 deletions src/lib/api/minds/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::error::Error;
use std::fmt;

#[repr(u8)]
#[derive(Debug)]
///Minds errors
pub enum MindsError {
///Authorization failed.
LoginFailed,
///Failed to send request to upload image.
ImageUploadSendError,
///Server rejected image upload.
ImageUploadServerReject,
///Server responded with invalid data.
///
///Should contain `id`
ImageUploadInvalidResponse,
///Failed to send request to perform text post.
PostUploadSendError,
///Server rejected posting.
PostUploadServerReject,
///Server responded with invalid data
///
///Should contain `id`
PostUploadInvalidResponse,

}

impl fmt::Display for MindsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description())
}
}

impl Error for MindsError {
fn description(&self) -> &str {
match self {
&MindsError::LoginFailed => "Login has failed",
&MindsError::ImageUploadSendError => "Failed to send request to upload image",
&MindsError::ImageUploadServerReject => "Server rejected upload of image",
&MindsError::ImageUploadInvalidResponse => "Server sent invalid response. Doesn't contain field id",
&MindsError::PostUploadSendError => "Failed to send request to perform text post",
&MindsError::PostUploadServerReject => "Server rejected posting",
&MindsError::PostUploadInvalidResponse => "Server sent invalid response. Doesn't contain field id",
}
}
}
Loading

0 comments on commit e4c5a4c

Please sign in to comment.