Expanded model - added YandexRequster struct for making api requests

Upped thiserror crate version to 2.0.3
This commit is contained in:
Egor 2024-11-30 04:16:21 +03:00
parent 0999692759
commit 79f21425b1
8 changed files with 268 additions and 145 deletions

70
Cargo.lock generated
View file

@ -55,7 +55,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -320,7 +320,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -543,7 +543,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -1231,7 +1231,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -1319,7 +1319,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -1406,9 +1406,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.89"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
@ -1800,7 +1800,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -2000,7 +2000,7 @@ dependencies = [
"sha2",
"smallvec",
"sqlformat",
"thiserror",
"thiserror 1.0.66",
"tokio",
"tokio-stream",
"tracing",
@ -2018,7 +2018,7 @@ dependencies = [
"quote",
"sqlx-core",
"sqlx-macros-core",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -2041,7 +2041,7 @@ dependencies = [
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
"syn 2.0.86",
"syn 2.0.90",
"tempfile",
"tokio",
"url",
@ -2084,7 +2084,7 @@ dependencies = [
"smallvec",
"sqlx-core",
"stringprep",
"thiserror",
"thiserror 1.0.66",
"tracing",
"whoami",
]
@ -2122,7 +2122,7 @@ dependencies = [
"smallvec",
"sqlx-core",
"stringprep",
"thiserror",
"thiserror 1.0.66",
"tracing",
"whoami",
]
@ -2186,9 +2186,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.86"
version = "2.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
dependencies = [
"proc-macro2",
"quote",
@ -2283,7 +2283,7 @@ dependencies = [
"serde_json",
"teloxide-core",
"teloxide-macros",
"thiserror",
"thiserror 1.0.66",
"tokio",
"tokio-stream",
"tokio-util",
@ -2313,7 +2313,7 @@ dependencies = [
"serde_with",
"take_mut",
"takecell",
"thiserror",
"thiserror 1.0.66",
"tokio",
"tokio-util",
"url",
@ -2360,7 +2360,16 @@ version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
dependencies = [
"thiserror-impl",
"thiserror-impl 1.0.66",
]
[[package]]
name = "thiserror"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
dependencies = [
"thiserror-impl 2.0.3",
]
[[package]]
@ -2371,7 +2380,18 @@ checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
name = "thiserror-impl"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
@ -2414,7 +2434,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -2498,7 +2518,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]
@ -2643,7 +2663,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
"wasm-bindgen-shared",
]
@ -2677,7 +2697,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -2945,7 +2965,7 @@ dependencies = [
"serde",
"sqlx",
"teloxide",
"thiserror",
"thiserror 2.0.3",
"tokio",
]
@ -2967,7 +2987,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.90",
]
[[package]]

View file

@ -8,7 +8,7 @@ teloxide = { version = "0.13", features = ["macros", "rustls"] }
log = "0.4"
pretty_env_logger = "0.5"
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
thiserror = "1.0.66"
thiserror = "2.0.3"
serde = "1.0.214"
dotenvy = "0.15.7"
reqwest = { version = "0.12.9", features = ["json"] }

View file

@ -12,9 +12,10 @@ CREATE TABLE IF NOT EXISTS proxies (
password TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS ya_apis (
CREATE TABLE IF NOT EXISTS requesters (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
api TEXT NOT NULL,
proxy_id INTEGER NOT NULL,
proxy_id INTEGER,
FOREIGN_KEY (proxy_id) REFERENCES proxies (id)
);

View file

@ -1,6 +1,3 @@
pub mod models;
pub mod schema;
use dotenvy::dotenv;
use std::collections::HashSet;
use std::env;

View file

@ -1,114 +1,3 @@
use bitflags::bitflags;
use std::{fmt::Display, net::IpAddr};
bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Permissions: u8 {
const WHITELIST_MODIFY = 0b00000001;
const YA_API_URL_MODIFY = 0b00000010;
const PROXY_MODIFY = 0b00000100;
}
}
impl Display for Permissions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_empty() {
return write!(f, "None");
}
bitflags::parser::to_writer(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)]
pub struct User {
username: String,
permissions: Permissions,
}
impl User {
fn new_with_perms(username: String, permissions: Permissions) -> Self {
Self {
username,
permissions,
}
}
fn new(username: String) -> Self {
Self::new_with_perms(username, Permissions::empty())
}
fn new_admin(username: String) -> Self {
Self::new_with_perms(username, Permissions::all())
}
fn get_username(&self) -> &str {
&self.username
}
fn get_permissions(&self) -> Permissions {
self.permissions
}
// grants new permissions and returns permissions that were modified
fn grant_permissions(&mut self, new_perms: Permissions) -> Permissions {
let updated = !self.permissions & new_perms;
self.permissions |= new_perms;
updated
}
// removes new permissions and returns permissions that were modified
fn remove_permissions(&mut self, remove_perms: Permissions) -> Permissions {
let updated = self.permissions & remove_perms;
self.permissions &= !remove_perms;
updated
}
}
#[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)]
pub struct Socks5Proxy {
ip: IpAddr,
port: u16,
user: String,
password: String,
}
impl Socks5Proxy {
fn new(ip: IpAddr, port: u16, user: String, password: String) -> Self {
Self {
ip,
port,
user,
password,
}
}
fn get_ip(&self) -> IpAddr {
self.ip
}
fn get_port(&self) -> u16 {
self.port
}
fn get_user(&self) -> &str {
&self.user
}
fn get_password(&self) -> &str {
&self.password
}
fn url(&self) -> String {
self.to_string()
}
}
impl Display for Socks5Proxy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"socks5://{}:{}@{}:{}",
self.user, self.password, self.ip, self.port
)
}
}
pub mod proxy;
pub mod requester;
pub mod user;

50
src/model/proxy.rs Normal file
View file

@ -0,0 +1,50 @@
use std::{fmt::Display, net::IpAddr};
#[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)]
pub struct Socks5Proxy {
ip: IpAddr,
port: u16,
user: String,
password: String,
}
impl Socks5Proxy {
pub fn new(ip: IpAddr, port: u16, user: String, password: String) -> Self {
Self {
ip,
port,
user,
password,
}
}
pub fn get_ip(&self) -> IpAddr {
self.ip
}
pub fn get_port(&self) -> u16 {
self.port
}
pub fn get_user(&self) -> &str {
&self.user
}
pub fn get_password(&self) -> &str {
&self.password
}
pub fn url(&self) -> String {
self.to_string()
}
}
impl Display for Socks5Proxy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"socks5://{}:{}@{}:{}",
self.user, self.password, self.ip, self.port
)
}
}

100
src/model/requester.rs Normal file
View file

@ -0,0 +1,100 @@
use reqwest::header::AUTHORIZATION;
use super::proxy::Socks5Proxy;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Period {
Today,
Yesterday,
Month,
Year,
}
#[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)]
pub struct YandexRequester {
token: String,
name: String,
proxy: Option<Socks5Proxy>,
}
#[derive(thiserror::Error, Debug)]
pub enum RequestError {
#[error("requester couldn't parse proxy: {0}")]
InvalidProxy(reqwest::Error),
#[error("requester failed to build client: {0}")]
ClientBuildFailed(reqwest::Error),
#[error("get request failed: {0}")]
GetRequestFailed(reqwest::Error),
}
impl YandexRequester {
const YANDEX_PARTNER_URL: &str = "https://partner2.yandex.ru/api/statistics2/get.json";
const YANDEX_PARTNER_DEFAULT_QUERY: [(&str, &str); 5] = [
("lang", "ru"),
("field", "shows"),
("field", "hits_render"),
("field", "partner_wo_nds"),
("field", "cpmv_partner_wo_nds"),
];
pub fn new_with_proxy(token: String, name: String, proxy: Socks5Proxy) -> Self {
Self {
token,
name,
proxy: Some(proxy),
}
}
pub fn new(token: String, name: String) -> Self {
Self {
token,
name,
proxy: None,
}
}
pub fn get_token(&self) -> &str {
&self.token
}
pub fn get_name(&self) -> &str {
&self.name
}
pub fn get_proxy(&self) -> Option<&Socks5Proxy> {
self.proxy.as_ref()
}
pub async fn summary(&self, period: Period) -> Result<(), RequestError> {
let period = Self::period_as_param(period);
let mut builder = reqwest::Client::builder();
if let Some(proxy) = &self.proxy {
let proxy =
reqwest::Proxy::all(proxy.url()).map_err(|e| RequestError::InvalidProxy(e))?;
builder = builder.proxy(proxy);
}
let client = builder
.build()
.map_err(|e| RequestError::ClientBuildFailed(e))?;
// TODO: deserialize response to json and return something already
let response = client
.get(Self::YANDEX_PARTNER_URL)
.header(AUTHORIZATION, self.token.clone())
.query(&Self::YANDEX_PARTNER_DEFAULT_QUERY)
.query(&("period", &period))
.send()
.await
.map_err(|e| RequestError::ClientBuildFailed(e))?;
Ok(())
}
fn period_as_param(period: Period) -> String {
match period {
Period::Today => "today",
Period::Yesterday => "yesterday",
Period::Month => "thismonth",
Period::Year => "thisyear",
}
.to_string()
}
}

66
src/model/user.rs Normal file
View file

@ -0,0 +1,66 @@
use bitflags::bitflags;
use std::fmt::Display;
bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Permissions: u8 {
const MANAGE_YA_APIS = 0b00000001;
const MANAGE_PROXIES = 0b00000010;
const ADD_USERS = 0b00000100;
const MANAGE_PERMISSIONS = 0b00001000;
}
}
impl Display for Permissions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_empty() {
return write!(f, "None");
}
bitflags::parser::to_writer(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, sqlx::FromRow)]
pub struct User {
username: String,
permissions: Permissions,
}
impl User {
pub fn new_with_perms(username: String, permissions: Permissions) -> Self {
Self {
username,
permissions,
}
}
pub fn new(username: String) -> Self {
Self::new_with_perms(username, Permissions::empty())
}
pub fn new_admin(username: String) -> Self {
Self::new_with_perms(username, Permissions::all())
}
pub fn get_username(&self) -> &str {
&self.username
}
pub fn get_permissions(&self) -> Permissions {
self.permissions
}
// grants new permissions and returns permissions that were modified
pub fn grant_permissions(&mut self, new_perms: Permissions) -> Permissions {
let updated = !self.permissions & new_perms;
self.permissions |= new_perms;
updated
}
// removes new permissions and returns permissions that were modified
pub fn remove_permissions(&mut self, remove_perms: Permissions) -> Permissions {
let updated = self.permissions & remove_perms;
self.permissions &= !remove_perms;
updated
}
}