Commit fe9cbe13 authored by Daniel García Moreno's avatar Daniel García Moreno

stickers: Initial load of sticker sets

parent eace31c5
extern crate url;
use globals;
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
use self::url::Url;
......@@ -10,6 +11,7 @@ use std::sync::mpsc::RecvError;
use error::Error;
use util::build_url;
use util::json_q;
use cache::CacheMap;
mod types;
......@@ -19,6 +21,7 @@ mod room;
mod sync;
mod media;
mod directory;
mod stickers;
pub use self::types::BKResponse;
pub use self::types::BKCommand;
......@@ -35,6 +38,9 @@ impl Backend {
user_id: String::from("Guest"),
access_token: String::from(""),
server_url: String::from("https://matrix.org"),
scalar_token: None,
scalar_url: String::from("https://scalar.vector.im"),
sticker_widget: None,
since: String::from(""),
rooms_since: String::from(""),
join_to_room: String::from(""),
......@@ -64,6 +70,40 @@ impl Backend {
client_url!(&base, path, params2)
}
fn get_scalar_token(&self) -> Result<String, Error> {
let s = self.data.lock().unwrap().scalar_url.clone();
let uid = self.data.lock().unwrap().user_id.clone();
let url = self.url(&format!("user/{}/openid/request_token", uid), vec![])?;
let js = json_q("post", &url, &json!({}), globals::TIMEOUT)?;
let vurl = Url::parse(&format!("{}/api/register", s))?;
let js = json_q("post", &vurl, &js, globals::TIMEOUT)?;
match js["scalar_token"].as_str() {
Some(st) => {
self.data.lock().unwrap().scalar_token = Some(st.to_string());
Ok(st.to_string())
}
None => Err(Error::BackendError),
}
}
fn vurl(&self, path: &str, params: Vec<(&str, String)>) -> Result<Url, Error> {
let s = self.data.lock().unwrap().scalar_url.clone();
let base = Url::parse(&s)?;
let token = self.data.lock().unwrap().scalar_token.clone();
let tk = match token {
None => self.get_scalar_token()?,
Some(t) => t.clone(),
};
let mut params2 = params.to_vec();
params2.push(("scalar_token", tk));
scalar_url!(&base, path, params2)
}
pub fn run(mut self) -> Sender<BKCommand> {
let (apptx, rx): (Sender<BKCommand>, Receiver<BKCommand>) = channel();
......@@ -262,6 +302,13 @@ impl Backend {
bkerror!(r, tx, BKResponse::DirectoryError);
}
// Stickers module
Ok(BKCommand::ListStickers) => {
let r = stickers::list(self);
bkerror!(r, tx, BKResponse::StickersError);
}
// Internal commands
Ok(BKCommand::ShutDown) => {
tx.send(BKResponse::ShutDown).unwrap();
......
extern crate serde_json;
use std::thread;
use util::json_q;
use globals;
//use std::thread;
use error::Error;
use backend::types::Backend;
use backend::types::BKResponse;
use types::StickerGroup;
use self::serde_json::Value as JsonValue;
/// Queries scalar.vector.im to list all the stickers
pub fn list(bk: &Backend) -> Result<(), Error> {
let widget = bk.data.lock().unwrap().sticker_widget.clone();
let widget_id = match widget {
None => {
let id = get_sticker_widget_id(bk)?;
bk.data.lock().unwrap().sticker_widget = Some(id.clone());
id
},
Some(id) => id.clone(),
};
let data = vec![
("widget_type", "m.stickerpicker".to_string()),
("widget_id", widget_id),
("filter_unpurchased", "true".to_string()),
];
let url = bk.vurl("widgets/assets", data)?;
let tx = bk.tx.clone();
get!(&url,
|r: JsonValue| {
let mut stickers = vec![];
for sticker_group in r["assets"].as_array().unwrap_or(&vec![]).iter() {
let group = StickerGroup::from_json(sticker_group);
stickers.push(group);
}
tx.send(BKResponse::Stickers(stickers)).unwrap();
},
|err| { tx.send(BKResponse::StickersError(err)).unwrap() }
);
Ok(())
}
pub fn get_sticker_widget_id(bk: &Backend) -> Result<String, Error> {
let data = json!({
"data": {},
"type": "m.stickerpicker",
});
let url = bk.vurl("widgets/request", vec![])?;
match json_q("post", &url, &data, globals::TIMEOUT) {
Ok(r) => {
let mut id = "".to_string();
if let Some(i) = r["id"].as_str() {
id = i.to_string();
}
if let Some(i) = r["data"]["id"].as_str() {
id = i.to_string();
}
match id.is_empty() {
true => Err(Error::BackendError),
false => Ok(id),
}
},
Err(Error::MatrixError(js)) => {
match js["data"]["id"].as_str() {
Some(id) => Ok(id.to_string()),
None => Err(Error::MatrixError(js.clone())),
}
},
Err(err) => { Err(err) }
}
}
......@@ -8,6 +8,7 @@ use types::Member;
use types::Protocol;
use types::Room;
use types::Event;
use types::StickerGroup;
use cache::CacheMap;
......@@ -54,6 +55,7 @@ pub enum BKCommand {
RejectInv(String),
UserSearch(String),
Invite(String, String),
ListStickers,
}
#[derive(Debug)]
......@@ -92,6 +94,7 @@ pub enum BKResponse {
AddedToFav(String, bool),
RoomNotifications(String, i32, i32),
UserSearch(Vec<Member>),
Stickers(Vec<StickerGroup>),
//errors
UserNameError(Error),
......@@ -123,6 +126,7 @@ pub enum BKResponse {
AcceptInvError(Error),
RejectInvError(Error),
InviteError(Error),
StickersError(Error),
}
#[derive(Debug)]
......@@ -135,6 +139,9 @@ pub struct BackendData {
pub user_id: String,
pub access_token: String,
pub server_url: String,
pub scalar_token: Option<String>,
pub scalar_url: String,
pub sticker_widget: Option<String>,
pub since: String,
pub rooms_since: String,
pub join_to_room: String,
......
......@@ -3,3 +3,4 @@ pub mod room;
pub mod protocol;
pub mod event;
pub mod message;
pub mod stickers;
extern crate serde_json;
use self::serde_json::Value as JsonValue;
#[derive(Debug)]
#[derive(Clone)]
#[derive(Serialize, Deserialize)]
pub struct Sticker {
pub name: String,
pub description: String,
pub file: String,
pub body: String,
pub thumbnail: String,
pub url: String,
}
#[derive(Debug)]
#[derive(Clone)]
#[derive(Serialize, Deserialize)]
pub struct StickerGroup {
pub name: String,
pub description: String,
pub price: i64,
pub purchased: bool,
pub thumbnail: String,
pub stickers: Vec<Sticker>,
}
impl StickerGroup {
pub fn from_json(js: &JsonValue) -> StickerGroup {
let mut stickers = vec![];
let d = &js["data"];
let purchased = js["purchased"].as_bool().unwrap_or_default();
let name = d["name"].as_str().unwrap_or_default().to_string();
let description = d["description"].as_str().unwrap_or_default().to_string();
let price = d["price"].as_i64().unwrap_or_default();
let thumbnail = d["thumbnail"].as_str().unwrap_or_default().to_string();
for img in d["images"].as_array().unwrap_or(&vec![]).iter() {
let c = &img["content"];
stickers.push(Sticker {
name: img["name"].as_str().unwrap_or_default().to_string(),
description: img["description"].as_str().unwrap_or_default().to_string(),
file: img["file"].as_str().unwrap_or_default().to_string(),
body: c["body"].as_str().unwrap_or_default().to_string(),
url: c["url"].as_str().unwrap_or_default().to_string(),
thumbnail: c["info"]["thumbnail_url"].as_str().unwrap_or_default().to_string(),
});
}
StickerGroup {
name,
description,
price,
purchased,
thumbnail,
stickers,
}
}
}
......@@ -5,3 +5,5 @@ pub use model::protocol::Protocol;
pub use model::message::Message;
pub use model::member::Member;
pub use model::member::MemberList;
pub use model::stickers::Sticker;
pub use model::stickers::StickerGroup;
......@@ -98,6 +98,13 @@ macro_rules! client_url {
)
}
#[macro_export]
macro_rules! scalar_url {
($b: expr, $path: expr, $params: expr) => (
build_url($b, &format!("api/{}", $path), $params)
)
}
#[macro_export]
macro_rules! media_url {
($b: expr, $path: expr, $params: expr) => (
......
......@@ -153,6 +153,9 @@ pub fn backend_loop(rx: Receiver<BKResponse>) {
Ok(BKResponse::UserSearch(users)) => {
APPOP!(user_search_finished, (users));
}
Ok(BKResponse::Stickers(stickers)) => {
APPOP!(stickers_loaded, (stickers));
}
// errors
Ok(BKResponse::NewRoomError(err, internal_id)) => {
......
......@@ -38,6 +38,7 @@ mod member;
mod invite;
mod about;
mod start_chat;
mod stickers;
pub use self::state::AppState;
use self::message::TmpMsg;
......
use appop::AppOp;
use types::StickerGroup;
use types::Sticker;
impl AppOp {
pub fn stickers_loaded(&self, stickers: Vec<StickerGroup>) {
for sg in stickers {
println!("STICKER GROUP: {}, {}", sg.name, sg.purchased);
}
}
}
......@@ -10,6 +10,8 @@ impl AppOp {
pub fn initial_sync(&self, show: bool) {
if show {
self.inapp_notify(&gettext("Syncing, this could take a while"));
// getting stickers
self.backend.send(BKCommand::ListStickers).unwrap();
} else {
self.hide_inapp_notify();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment