aob-lemmy-bot/src/lemmy.rs

305 lines
9.1 KiB
Rust
Raw Normal View History

2023-12-30 00:27:11 +00:00
use crate::config::Config;
use crate::{write_error, HTTP_CLIENT};
use lemmy_api_common::community::{ListCommunities, ListCommunitiesResponse};
use lemmy_api_common::lemmy_db_views::structs::PostView;
use lemmy_api_common::person::{Login, LoginResponse};
use lemmy_api_common::post::{CreatePost, FeaturePost, GetPosts, GetPostsResponse};
use lemmy_api_common::sensitive::Sensitive;
use lemmy_db_schema::newtypes::{CommunityId, PostId};
use lemmy_db_schema::{ListingType, PostFeatureType};
use reqwest::StatusCode;
2023-12-30 00:27:11 +00:00
use std::collections::HashMap;
2024-01-08 20:06:52 +00:00
use url::Url;
pub(crate) struct Lemmy {
jwt_token: Sensitive<String>,
instance: String,
}
2024-01-08 20:06:52 +00:00
#[derive(Debug, Clone)]
pub(crate) struct PostInfoInner {
pub(crate) title: String,
pub(crate) url: Url,
}
pub(crate) trait PostInfo {
fn get_info(&self) -> PostInfoInner;
fn get_description(&self) -> Option<String>;
}
pub(crate) async fn login(config: &Config) -> Result<Lemmy, ()> {
let login_params = Login {
username_or_email: config.get_username(),
password: config.get_password(),
totp_2fa_token: None,
};
2023-12-17 21:29:18 +00:00
let response = match HTTP_CLIENT
.post(config.instance.to_owned() + "/api/v3/user/login")
.json(&login_params)
.send()
2023-12-30 00:27:11 +00:00
.await
{
2023-12-17 21:29:18 +00:00
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
match response.status() {
StatusCode::OK => {
2023-12-30 00:27:11 +00:00
let data: LoginResponse = response
.json()
.await
.expect("Successful Login Request should return JSON");
match data.jwt {
Some(token) => Ok(Lemmy {
jwt_token: token.clone(),
instance: config.instance.to_owned(),
}),
None => {
let err_msg = "Login did not return JWT token. Are the credentials valid?".to_owned();
write_error(err_msg);
2023-12-29 23:53:00 +00:00
Err(())
}
}
2023-12-30 00:27:11 +00:00
}
status => {
let err_msg = format!("Unexpected HTTP Status '{}' during Login", status);
write_error(err_msg);
2023-12-29 23:53:00 +00:00
Err(())
}
}
}
impl Lemmy {
pub(crate) async fn post(&self, post: CreatePost) -> Result<PostId, ()> {
2023-12-17 21:29:18 +00:00
let response = match HTTP_CLIENT
.post(format!("{}/api/v3/post", &self.instance))
.bearer_auth(&self.jwt_token.to_string())
.json(&post)
.send()
2023-12-30 00:27:11 +00:00
.await
{
Ok(data) => match data.text().await {
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
return Err(());
2023-12-17 21:29:18 +00:00
}
},
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
let json_data = match serde_json::from_str::<HashMap<&str, PostView>>(&response) {
2023-12-17 21:29:18 +00:00
Ok(mut data) => data.remove("post_view").expect("Element should be present"),
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
Ok(json_data.post.id)
}
async fn feature(&self, params: FeaturePost) -> Result<PostView, ()> {
2023-12-17 21:29:18 +00:00
let response = match HTTP_CLIENT
.post(format!("{}/api/v3/post/feature", &self.instance))
.bearer_auth(&self.jwt_token.to_string())
.json(&params)
.send()
2023-12-30 00:27:11 +00:00
.await
{
Ok(data) => match data.text().await {
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
return Err(());
2023-12-17 21:29:18 +00:00
}
},
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
let json_data = match serde_json::from_str::<HashMap<&str, PostView>>(&response) {
2023-12-17 21:29:18 +00:00
Ok(mut data) => data.remove("post_view").expect("Element should be present"),
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
Ok(json_data)
}
pub(crate) async fn unpin(&self, post_id: PostId, location: PostFeatureType) -> Result<PostView, ()> {
let pin_params = FeaturePost {
post_id,
featured: false,
feature_type: location,
};
self.feature(pin_params).await
}
pub(crate) async fn pin(&self, post_id: PostId, location: PostFeatureType) -> Result<PostView, ()> {
let pin_params = FeaturePost {
post_id,
featured: true,
feature_type: location,
};
self.feature(pin_params).await
}
pub(crate) async fn get_community_pinned(&self, community: CommunityId) -> Result<Vec<PostView>, ()> {
let list_params = GetPosts {
community_id: Some(community),
type_: Some(ListingType::Local),
..Default::default()
};
2023-12-17 21:29:18 +00:00
let response = match HTTP_CLIENT
.get(format!("{}/api/v3/post/list", &self.instance))
.bearer_auth(&self.jwt_token.to_string())
.query(&list_params)
.send()
2023-12-30 00:27:11 +00:00
.await
{
Ok(data) => match data.text().await {
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
return Err(());
2023-12-17 21:29:18 +00:00
}
},
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
let json_data: GetPostsResponse = match serde_json::from_str(&response) {
2023-12-17 21:29:18 +00:00
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
2023-12-30 00:27:11 +00:00
Ok(json_data
.posts
.iter()
.filter(|post| post.post.featured_community)
.cloned()
2023-12-30 00:27:11 +00:00
.collect())
}
pub(crate) async fn get_local_pinned(&self) -> Result<Vec<PostView>, ()> {
let list_params = GetPosts {
type_: Some(ListingType::Local),
..Default::default()
};
2023-12-17 21:29:18 +00:00
let response = match HTTP_CLIENT
.get(format!("{}/api/v3/post/list", &self.instance))
.bearer_auth(&self.jwt_token.to_string())
.query(&list_params)
.send()
2023-12-30 00:27:11 +00:00
.await
{
Ok(data) => match data.text().await {
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
return Err(());
2023-12-17 21:29:18 +00:00
}
},
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
let json_data: GetPostsResponse = match serde_json::from_str(&response) {
2023-12-17 21:29:18 +00:00
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
2023-12-30 00:27:11 +00:00
Ok(json_data
.posts
.iter()
.filter(|post| post.post.featured_local)
.cloned()
2023-12-30 00:27:11 +00:00
.collect())
}
pub(crate) async fn get_communities(&self) -> Result<HashMap<String, CommunityId>, ()> {
let list_params = ListCommunities {
type_: Some(ListingType::Local),
..Default::default()
};
2023-12-17 21:29:18 +00:00
let response = match HTTP_CLIENT
.get(format!("{}/api/v3/community/list", &self.instance))
.bearer_auth(&self.jwt_token.to_string())
.query(&list_params)
.send()
2023-12-30 00:27:11 +00:00
.await
{
Ok(data) => match data.text().await {
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
return Err(());
2023-12-17 21:29:18 +00:00
}
},
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
let json_data: ListCommunitiesResponse = match serde_json::from_str(&response) {
2023-12-17 21:29:18 +00:00
Ok(data) => data,
Err(e) => {
let err_msg = format!("{e}");
write_error(err_msg);
2023-12-30 00:27:11 +00:00
return Err(());
}
2023-12-17 21:29:18 +00:00
};
let mut communities: HashMap<String, CommunityId> = HashMap::new();
for community_view in json_data.communities {
let community = community_view.community;
communities.insert(community.name, community.id);
}
2023-12-17 19:35:37 +00:00
Ok(communities)
}
}