refactors and add timestamp to meme display
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
1463a3cf0d
commit
3c395a34a7
10 changed files with 70 additions and 30 deletions
|
@ -16,18 +16,19 @@ name = "jm"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
jm_client_core = { path = "../jm_client_core" }
|
||||
|
||||
anyhow = "1.0.34"
|
||||
chrono = "0.4.19"
|
||||
clap = "2.33.3"
|
||||
env_logger = "0.8.2"
|
||||
fuzzy-matcher = "0.3.7"
|
||||
jm_client_core = { path = "../jm_client_core" }
|
||||
log = "0.4.11"
|
||||
opener = "0.4.1"
|
||||
reqwest = { version = "0.10", features = ["stream"] }
|
||||
structopt = "0.3.21"
|
||||
term-table = "1.3.0"
|
||||
term_size = "0.3.2"
|
||||
tokio = { version = "0.2.23", features = ["macros", "fs", "process"] }
|
||||
url = "2.2.0"
|
||||
reqwest = { version = "0.10", features = ["stream"] }
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::util::{self, IntoTableRow};
|
||||
use crate::table::{self, IntoTableRow};
|
||||
use jm_client_core::util::api;
|
||||
use reqwest::Client;
|
||||
|
||||
|
@ -7,7 +7,7 @@ pub async fn run(http: &Client) -> anyhow::Result<()> {
|
|||
let mut cats = api::cats(http).await?.clone();
|
||||
cats.sort_by(|a, b| a.id.cmp(&b.id));
|
||||
|
||||
let mut table = util::list_table();
|
||||
let mut table = table::list_table();
|
||||
|
||||
for cat in &cats {
|
||||
table.add_row(cat.into_table_row());
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
use crate::util::IntoTableRow;
|
||||
use crate::table::{self, IntoTableRow};
|
||||
use jm_client_core::util::{self, api, MemeSorting};
|
||||
|
||||
pub async fn run(
|
||||
|
@ -45,7 +45,7 @@ pub async fn run(
|
|||
s.sort_with(&mut memes);
|
||||
}
|
||||
|
||||
let mut table = crate::util::list_table();
|
||||
let mut table = table::list_table();
|
||||
|
||||
for m in memes.iter() {
|
||||
table.add_row(m.into_table_row());
|
||||
|
|
|
@ -3,7 +3,7 @@ use log::info;
|
|||
use reqwest::Client;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::util::IntoTableRow;
|
||||
use crate::table::{self, IntoTableRow};
|
||||
use jm_client_core::util::{self, api};
|
||||
|
||||
pub async fn run(
|
||||
|
@ -51,7 +51,7 @@ pub async fn run(
|
|||
matches.sort_by(|a, b| b.1.cmp(&a.1));
|
||||
let res = match (firsturl, cat) {
|
||||
(false, false) => {
|
||||
let mut table = crate::util::list_table();
|
||||
let mut table = table::list_table();
|
||||
|
||||
for m in matches {
|
||||
table.add_row(m.0.into_table_row());
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::util::IntoTableRow;
|
||||
use crate::table::{self, IntoTableRow};
|
||||
use anyhow::Result;
|
||||
use jm_client_core::util::api;
|
||||
use reqwest::Client;
|
||||
|
||||
pub async fn run(http: &Client) -> Result<()> {
|
||||
let users = api::users(http).await?;
|
||||
let mut table = crate::util::list_table();
|
||||
let mut table = table::list_table();
|
||||
|
||||
for u in users {
|
||||
table.add_row(u.into_table_row())
|
||||
|
|
|
@ -3,8 +3,8 @@ use jm_client_core::util::MemeSorting;
|
|||
use reqwest::Client;
|
||||
use structopt::StructOpt;
|
||||
|
||||
mod api;
|
||||
mod commands;
|
||||
mod table;
|
||||
mod util;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
|
@ -75,7 +75,7 @@ enum Cmd {
|
|||
#[structopt(
|
||||
long,
|
||||
short,
|
||||
help = "how to sort the results. can be id, user, category or link"
|
||||
help = "how to sort the results. can be id, user, category, timestamp or link"
|
||||
)]
|
||||
sort: Option<MemeSorting>,
|
||||
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
use crate::util::IntoTableRow;
|
||||
use chrono::{Local, TimeZone};
|
||||
use jm_client_core::api::{Category, Meme, User};
|
||||
use term_table::{row::Row, table_cell::TableCell};
|
||||
use term_table::{row::Row, table_cell::TableCell, Table, TableBuilder, TableStyle};
|
||||
|
||||
/// returns an empty table with the correct format settings for lists
|
||||
pub fn list_table<'a>() -> Table<'a> {
|
||||
TableBuilder::new()
|
||||
.style(TableStyle::simple())
|
||||
.separate_rows(false)
|
||||
.has_top_boarder(false)
|
||||
.has_bottom_boarder(false)
|
||||
.build()
|
||||
}
|
||||
|
||||
pub trait IntoTableRow {
|
||||
fn into_table_row(&self) -> term_table::row::Row;
|
||||
}
|
||||
|
||||
impl IntoTableRow for Category {
|
||||
fn into_table_row(&self) -> Row<'_> {
|
||||
|
@ -14,6 +28,7 @@ impl IntoTableRow for Meme {
|
|||
TableCell::new(&self.link),
|
||||
TableCell::new(&self.category),
|
||||
TableCell::new(&self.user),
|
||||
TableCell::new(Local.timestamp(self.timestamp, 0).format("%F %R")),
|
||||
])
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
use term_table::{Table, TableBuilder, TableStyle};
|
||||
use tokio::process::Command;
|
||||
|
||||
pub async fn open_link(url: &str) -> anyhow::Result<()> {
|
||||
|
@ -11,17 +10,3 @@ pub async fn open_link(url: &str) -> anyhow::Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// returns an empty table with the correct format settings for lists
|
||||
pub fn list_table<'a>() -> Table<'a> {
|
||||
TableBuilder::new()
|
||||
.style(TableStyle::simple())
|
||||
.separate_rows(false)
|
||||
.has_top_boarder(false)
|
||||
.has_bottom_boarder(false)
|
||||
.build()
|
||||
}
|
||||
|
||||
pub trait IntoTableRow {
|
||||
fn into_table_row(&self) -> term_table::row::Row;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Deserializer, de::{self, Visitor}};
|
||||
|
||||
#[derive(Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct UpResp {
|
||||
|
@ -34,6 +34,8 @@ pub struct Meme {
|
|||
pub path: String,
|
||||
pub category: String,
|
||||
pub user: String,
|
||||
#[serde(deserialize_with = "deserialize_timestamp")]
|
||||
pub timestamp: i64,
|
||||
}
|
||||
|
||||
impl Meme {
|
||||
|
@ -62,3 +64,37 @@ impl User {
|
|||
.or(self.userdir.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_timestamp<'de, D>(deserializer: D) -> Result<i64, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct Vis;
|
||||
|
||||
impl<'de> Visitor<'de> for Vis {
|
||||
type Value = i64;
|
||||
|
||||
fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
fmt.write_str(
|
||||
"A timestamp in the form of a string or i64 (because tilera doesn't know integers \
|
||||
exist)",
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
v.parse().map_err(|_| de::Error::invalid_value(de::Unexpected::Str(v), &self))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(Vis)
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ pub enum MemeSorting {
|
|||
Link,
|
||||
Category,
|
||||
User,
|
||||
Timestamp,
|
||||
}
|
||||
|
||||
impl MemeSorting {
|
||||
|
@ -171,6 +172,7 @@ impl MemeSorting {
|
|||
Self::Link => sort!(memes, link),
|
||||
Self::Category => sort!(memes, category),
|
||||
Self::User => sort!(memes, user),
|
||||
Self::Timestamp => memes.sort_by(|a, b| b.timestamp.cmp(&a.timestamp)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,6 +186,7 @@ impl FromStr for MemeSorting {
|
|||
"link" => Ok(Self::Link),
|
||||
"category" => Ok(Self::Category),
|
||||
"user" => Ok(Self::User),
|
||||
"timestamp" => Ok(Self::Timestamp),
|
||||
_ => bail!("Invalid Meme sorting! options are id, link, category and user!"),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue