mirror of
https://github.com/flibusta-apps/telegram_files_cache_server.git
synced 2025-12-06 06:35:38 +01:00
Add pre-commit config
This commit is contained in:
7
.pre-commit-config.yaml
Normal file
7
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/doublify/pre-commit-rust
|
||||||
|
rev: v1.0
|
||||||
|
hooks:
|
||||||
|
- id: fmt
|
||||||
|
- id: cargo-check
|
||||||
|
- id: clippy
|
||||||
@@ -23,15 +23,13 @@ pub struct Config {
|
|||||||
pub files_api_key: String,
|
pub files_api_key: String,
|
||||||
pub files_url: String,
|
pub files_url: String,
|
||||||
|
|
||||||
pub sentry_dsn: String
|
pub sentry_dsn: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn get_env(env: &'static str) -> String {
|
fn get_env(env: &'static str) -> String {
|
||||||
std::env::var(env).unwrap_or_else(|_| panic!("Cannot get the {} env variable", env))
|
std::env::var(env).unwrap_or_else(|_| panic!("Cannot get the {} env variable", env))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn load() -> Config {
|
pub fn load() -> Config {
|
||||||
Config {
|
Config {
|
||||||
@@ -57,12 +55,9 @@ impl Config {
|
|||||||
files_api_key: get_env("FILES_SERVER_API_KEY"),
|
files_api_key: get_env("FILES_SERVER_API_KEY"),
|
||||||
files_url: get_env("FILES_SERVER_URL"),
|
files_url: get_env("FILES_SERVER_URL"),
|
||||||
|
|
||||||
sentry_dsn: get_env("SENTRY_DSN")
|
sentry_dsn: get_env("SENTRY_DSN"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static CONFIG: Lazy<Config> = Lazy::new(Config::load);
|
||||||
pub static CONFIG: Lazy<Config> = Lazy::new(|| {
|
|
||||||
Config::load()
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::{prisma::PrismaClient, config::CONFIG};
|
use crate::{config::CONFIG, prisma::PrismaClient};
|
||||||
|
|
||||||
|
|
||||||
pub async fn get_prisma_client() -> PrismaClient {
|
pub async fn get_prisma_client() -> PrismaClient {
|
||||||
let database_url: String = format!(
|
let database_url: String = format!(
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod prisma;
|
pub mod prisma;
|
||||||
pub mod views;
|
|
||||||
pub mod services;
|
pub mod services;
|
||||||
|
pub mod views;
|
||||||
|
|
||||||
|
use sentry::{integrations::debug_images::DebugImagesIntegration, types::Dsn, ClientOptions};
|
||||||
use std::{net::SocketAddr, str::FromStr};
|
use std::{net::SocketAddr, str::FromStr};
|
||||||
use sentry::{ClientOptions, types::Dsn, integrations::debug_images::DebugImagesIntegration};
|
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::views::get_router;
|
use crate::views::get_router;
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let options = ClientOptions {
|
let options = ClientOptions {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// Code generated by Prisma Client Rust. DO NOT EDIT
|
// Code generated by Prisma Client Rust. DO NOT EDIT
|
||||||
|
|
||||||
pub static DATAMODEL_STR: &str =
|
#![allow(clippy::all)]
|
||||||
include_str!("../prisma/schema.prisma");
|
|
||||||
|
pub static DATAMODEL_STR: &str = include_str!("../prisma/schema.prisma");
|
||||||
static DATABASE_STR: &str = "postgresql";
|
static DATABASE_STR: &str = "postgresql";
|
||||||
pub async fn new_client() -> Result<PrismaClient, ::prisma_client_rust::NewClientError> {
|
pub async fn new_client() -> Result<PrismaClient, ::prisma_client_rust::NewClientError> {
|
||||||
PrismaClient::_builder().build().await
|
PrismaClient::_builder().build().await
|
||||||
@@ -21,9 +22,7 @@ pub mod cached_file {
|
|||||||
pub mod id {
|
pub mod id {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
use super::{
|
use super::{OrderByParam, SetParam, UncheckedSetParam, UniqueWhereParam, WhereParam};
|
||||||
OrderByParam, SetParam, UncheckedSetParam, UniqueWhereParam, WhereParam,
|
|
||||||
};
|
|
||||||
pub const NAME: &str = "id";
|
pub const NAME: &str = "id";
|
||||||
pub struct Set(pub i32);
|
pub struct Set(pub i32);
|
||||||
impl From<Set> for SetParam {
|
impl From<Set> for SetParam {
|
||||||
@@ -92,9 +91,7 @@ pub mod cached_file {
|
|||||||
pub mod object_id {
|
pub mod object_id {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
use super::{
|
use super::{OrderByParam, SetParam, UncheckedSetParam, WhereParam};
|
||||||
OrderByParam, SetParam, UncheckedSetParam, WhereParam,
|
|
||||||
};
|
|
||||||
pub const NAME: &str = "object_id";
|
pub const NAME: &str = "object_id";
|
||||||
pub struct Set(pub i32);
|
pub struct Set(pub i32);
|
||||||
impl From<Set> for SetParam {
|
impl From<Set> for SetParam {
|
||||||
@@ -167,9 +164,7 @@ pub mod cached_file {
|
|||||||
pub mod object_type {
|
pub mod object_type {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
use super::{
|
use super::{OrderByParam, SetParam, UncheckedSetParam, WhereParam};
|
||||||
OrderByParam, SetParam, UncheckedSetParam, WhereParam,
|
|
||||||
};
|
|
||||||
pub const NAME: &str = "object_type";
|
pub const NAME: &str = "object_type";
|
||||||
pub struct Set(pub String);
|
pub struct Set(pub String);
|
||||||
impl From<Set> for SetParam {
|
impl From<Set> for SetParam {
|
||||||
@@ -234,9 +229,7 @@ pub mod cached_file {
|
|||||||
pub mod message_id {
|
pub mod message_id {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
use super::{
|
use super::{OrderByParam, SetParam, UncheckedSetParam, UniqueWhereParam, WhereParam};
|
||||||
OrderByParam, SetParam, UncheckedSetParam, UniqueWhereParam, WhereParam,
|
|
||||||
};
|
|
||||||
pub const NAME: &str = "message_id";
|
pub const NAME: &str = "message_id";
|
||||||
pub struct Set(pub i64);
|
pub struct Set(pub i64);
|
||||||
impl From<Set> for SetParam {
|
impl From<Set> for SetParam {
|
||||||
@@ -309,9 +302,7 @@ pub mod cached_file {
|
|||||||
pub mod chat_id {
|
pub mod chat_id {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
use super::{
|
use super::{OrderByParam, SetParam, UncheckedSetParam, WhereParam};
|
||||||
OrderByParam, SetParam, UncheckedSetParam, WhereParam,
|
|
||||||
};
|
|
||||||
pub const NAME: &str = "chat_id";
|
pub const NAME: &str = "chat_id";
|
||||||
pub struct Set(pub i64);
|
pub struct Set(pub i64);
|
||||||
impl From<Set> for SetParam {
|
impl From<Set> for SetParam {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ pub async fn get_books(
|
|||||||
("page", page.to_string()),
|
("page", page.to_string()),
|
||||||
("size", page_size.to_string()),
|
("size", page_size.to_string()),
|
||||||
("uploaded_gte", uploaded_gte),
|
("uploaded_gte", uploaded_gte),
|
||||||
("uploaded_lte", uploaded_lte)
|
("uploaded_lte", uploaded_lte),
|
||||||
];
|
];
|
||||||
|
|
||||||
_make_request("/api/v1/books/base/", params).await
|
_make_request("/api/v1/books/base/", params).await
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct Source {
|
pub struct Source {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
@@ -41,7 +40,7 @@ pub struct BookWithRemote {
|
|||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct BaseBook {
|
pub struct BaseBook {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub available_types: Vec<String>
|
pub available_types: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BookWithRemote {
|
impl BookWithRemote {
|
||||||
@@ -59,7 +58,6 @@ impl BookWithRemote {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl BookAuthor {
|
impl BookAuthor {
|
||||||
pub fn get_caption(self) -> String {
|
pub fn get_caption(self) -> String {
|
||||||
let mut parts: Vec<String> = vec![];
|
let mut parts: Vec<String> = vec![];
|
||||||
@@ -82,21 +80,13 @@ impl BookAuthor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl BookWithRemote {
|
impl BookWithRemote {
|
||||||
pub fn get_caption(self) -> String {
|
pub fn get_caption(self) -> String {
|
||||||
let BookWithRemote {
|
let BookWithRemote { title, authors, .. } = self;
|
||||||
title,
|
|
||||||
authors,
|
|
||||||
..
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
let caption_title = format!("📖 {title}");
|
let caption_title = format!("📖 {title}");
|
||||||
|
|
||||||
let author_captions: Vec<String> = authors
|
let author_captions: Vec<String> = authors.into_iter().map(|a| a.get_caption()).collect();
|
||||||
.into_iter()
|
|
||||||
.map(|a| a.get_caption())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut author_parts: Vec<String> = vec![];
|
let mut author_parts: Vec<String> = vec![];
|
||||||
let mut author_parts_len = 3;
|
let mut author_parts_len = 3;
|
||||||
@@ -116,7 +106,6 @@ impl BookWithRemote {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct Page<T> {
|
pub struct Page<T> {
|
||||||
pub items: Vec<T>,
|
pub items: Vec<T>,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::io::{Write, Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom, Write};
|
||||||
|
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
@@ -7,7 +7,6 @@ use tempfile::SpooledTempFile;
|
|||||||
use tokio::io::AsyncRead;
|
use tokio::io::AsyncRead;
|
||||||
use tokio_util::compat::FuturesAsyncReadCompatExt;
|
use tokio_util::compat::FuturesAsyncReadCompatExt;
|
||||||
|
|
||||||
|
|
||||||
pub struct DownloadResult {
|
pub struct DownloadResult {
|
||||||
pub response: Response,
|
pub response: Response,
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct FilenameData {
|
pub struct FilenameData {
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
pub filename_ascii: String
|
pub filename_ascii: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct DownloadError {
|
struct DownloadError {
|
||||||
status_code: StatusCode,
|
status_code: StatusCode,
|
||||||
@@ -26,11 +24,10 @@ impl fmt::Display for DownloadError {
|
|||||||
|
|
||||||
impl std::error::Error for DownloadError {}
|
impl std::error::Error for DownloadError {}
|
||||||
|
|
||||||
|
|
||||||
pub async fn download_from_downloader(
|
pub async fn download_from_downloader(
|
||||||
source_id: u32,
|
source_id: u32,
|
||||||
remote_id: u32,
|
remote_id: u32,
|
||||||
object_type: String
|
object_type: String,
|
||||||
) -> Result<Response, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<Response, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/download/{source_id}/{remote_id}/{object_type}",
|
"{}/download/{source_id}/{remote_id}/{object_type}",
|
||||||
@@ -45,16 +42,17 @@ pub async fn download_from_downloader(
|
|||||||
.error_for_status()?;
|
.error_for_status()?;
|
||||||
|
|
||||||
if response.status() == StatusCode::NO_CONTENT {
|
if response.status() == StatusCode::NO_CONTENT {
|
||||||
return Err(Box::new(DownloadError { status_code: StatusCode::NO_CONTENT }))
|
return Err(Box::new(DownloadError {
|
||||||
|
status_code: StatusCode::NO_CONTENT,
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn get_filename(
|
pub async fn get_filename(
|
||||||
object_id: i32,
|
object_id: i32,
|
||||||
object_type: String
|
object_type: String,
|
||||||
) -> Result<FilenameData, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<FilenameData, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/filename/{object_id}/{object_type}",
|
"{}/filename/{object_id}/{object_type}",
|
||||||
@@ -70,8 +68,6 @@ pub async fn get_filename(
|
|||||||
|
|
||||||
match response.json::<FilenameData>().await {
|
match response.json::<FilenameData>().await {
|
||||||
Ok(v) => Ok(v),
|
Ok(v) => Ok(v),
|
||||||
Err(err) => {
|
Err(err) => Err(Box::new(err)),
|
||||||
Err(Box::new(err))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,21 @@ use std::io::Read;
|
|||||||
|
|
||||||
use async_stream::stream;
|
use async_stream::stream;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use minio_rsc::{provider::StaticProvider, Minio, types::args::{ObjectArgs, PresignedArgs}, errors::MinioError};
|
use minio_rsc::{
|
||||||
|
errors::MinioError,
|
||||||
|
provider::StaticProvider,
|
||||||
|
types::args::{ObjectArgs, PresignedArgs},
|
||||||
|
Minio,
|
||||||
|
};
|
||||||
use tempfile::SpooledTempFile;
|
use tempfile::SpooledTempFile;
|
||||||
|
|
||||||
use crate::config;
|
use crate::config;
|
||||||
|
|
||||||
|
|
||||||
pub fn get_minio() -> Minio {
|
pub fn get_minio() -> Minio {
|
||||||
let provider = StaticProvider::new(
|
let provider = StaticProvider::new(
|
||||||
&config::CONFIG.minio_access_key,
|
&config::CONFIG.minio_access_key,
|
||||||
&config::CONFIG.minio_secret_key,
|
&config::CONFIG.minio_secret_key,
|
||||||
None
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
Minio::builder()
|
Minio::builder()
|
||||||
@@ -23,8 +27,9 @@ pub fn get_minio() -> Minio {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_stream(
|
||||||
pub fn get_stream(mut temp_file: Box<dyn Read + Send>) -> impl futures_core::Stream<Item = Result<Bytes, MinioError>> {
|
mut temp_file: Box<dyn Read + Send>,
|
||||||
|
) -> impl futures_core::Stream<Item = Result<Bytes, MinioError>> {
|
||||||
stream! {
|
stream! {
|
||||||
let mut buf = [0; 2048];
|
let mut buf = [0; 2048];
|
||||||
|
|
||||||
@@ -38,8 +43,10 @@ pub fn get_stream(mut temp_file: Box<dyn Read + Send>) -> impl futures_core::Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn upload_to_minio(
|
||||||
pub async fn upload_to_minio(archive: SpooledTempFile, filename: String) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
archive: SpooledTempFile,
|
||||||
|
filename: String,
|
||||||
|
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let minio = get_minio();
|
let minio = get_minio();
|
||||||
|
|
||||||
let is_bucket_exist = match minio.bucket_exists(&config::CONFIG.minio_bucket).await {
|
let is_bucket_exist = match minio.bucket_exists(&config::CONFIG.minio_bucket).await {
|
||||||
@@ -53,20 +60,24 @@ pub async fn upload_to_minio(archive: SpooledTempFile, filename: String) -> Resu
|
|||||||
|
|
||||||
let data_stream = get_stream(Box::new(archive));
|
let data_stream = get_stream(Box::new(archive));
|
||||||
|
|
||||||
if let Err(err) = minio.put_object_stream(
|
if let Err(err) = minio
|
||||||
ObjectArgs::new(&config::CONFIG.minio_bucket, filename.clone()),
|
.put_object_stream(
|
||||||
Box::pin(data_stream)
|
ObjectArgs::new(&config::CONFIG.minio_bucket, filename.clone()),
|
||||||
).await {
|
Box::pin(data_stream),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err(Box::new(err));
|
return Err(Box::new(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
let link = match minio.presigned_get_object(
|
let link = match minio
|
||||||
PresignedArgs::new(&config::CONFIG.minio_bucket, filename)
|
.presigned_get_object(PresignedArgs::new(&config::CONFIG.minio_bucket, filename))
|
||||||
).await {
|
.await
|
||||||
|
{
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(Box::new(err));
|
return Err(Box::new(err));
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(link)
|
Ok(link)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
pub mod book_library;
|
pub mod book_library;
|
||||||
pub mod download_utils;
|
pub mod download_utils;
|
||||||
pub mod telegram_files;
|
|
||||||
pub mod downloader;
|
pub mod downloader;
|
||||||
pub mod minio;
|
pub mod minio;
|
||||||
|
pub mod telegram_files;
|
||||||
|
|
||||||
use chrono::Duration;
|
use chrono::Duration;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@@ -10,16 +10,25 @@ use tracing::log;
|
|||||||
|
|
||||||
use crate::{prisma::cached_file, views::Database};
|
use crate::{prisma::cached_file, views::Database};
|
||||||
|
|
||||||
use self::{download_utils::{DownloadResult, response_to_tempfile}, telegram_files::{download_from_telegram_files, UploadData, upload_to_telegram_files}, downloader::{get_filename, FilenameData, download_from_downloader}, book_library::{get_book, types::BaseBook, get_books}, minio::upload_to_minio};
|
use self::{
|
||||||
|
book_library::{get_book, get_books, types::BaseBook},
|
||||||
|
download_utils::{response_to_tempfile, DownloadResult},
|
||||||
|
downloader::{download_from_downloader, get_filename, FilenameData},
|
||||||
|
minio::upload_to_minio,
|
||||||
|
telegram_files::{download_from_telegram_files, upload_to_telegram_files, UploadData},
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn get_cached_file_or_cache(
|
pub async fn get_cached_file_or_cache(
|
||||||
object_id: i32,
|
object_id: i32,
|
||||||
object_type: String,
|
object_type: String,
|
||||||
db: Database
|
db: Database,
|
||||||
) -> Option<cached_file::Data> {
|
) -> Option<cached_file::Data> {
|
||||||
let cached_file = db.cached_file()
|
let cached_file = db
|
||||||
.find_unique(cached_file::object_id_object_type(object_id, object_type.clone()))
|
.cached_file()
|
||||||
|
.find_unique(cached_file::object_id_object_type(
|
||||||
|
object_id,
|
||||||
|
object_type.clone(),
|
||||||
|
))
|
||||||
.exec()
|
.exec()
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -30,80 +39,77 @@ pub async fn get_cached_file_or_cache(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn cache_file(
|
pub async fn cache_file(
|
||||||
object_id: i32,
|
object_id: i32,
|
||||||
object_type: String,
|
object_type: String,
|
||||||
db: Database
|
db: Database,
|
||||||
) -> Option<cached_file::Data> {
|
) -> Option<cached_file::Data> {
|
||||||
let book = match get_book(object_id).await {
|
let book = match get_book(object_id).await {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("{:?}", err);
|
log::error!("{:?}", err);
|
||||||
return None;
|
return None;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let downloader_result = match download_from_downloader(
|
let downloader_result =
|
||||||
book.source.id,
|
match download_from_downloader(book.source.id, book.remote_id, object_type.clone()).await {
|
||||||
book.remote_id,
|
Ok(v) => v,
|
||||||
object_type.clone()
|
Err(err) => {
|
||||||
).await {
|
log::error!("{:?}", err);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let UploadData {
|
||||||
|
chat_id,
|
||||||
|
message_id,
|
||||||
|
} = match upload_to_telegram_files(downloader_result, book.get_caption()).await {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("{:?}", err);
|
log::error!("{:?}", err);
|
||||||
return None;
|
return None;
|
||||||
},
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let UploadData { chat_id, message_id } = match upload_to_telegram_files(
|
|
||||||
downloader_result,
|
|
||||||
book.get_caption()
|
|
||||||
).await {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(err) => {
|
|
||||||
log::error!("{:?}", err);
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
db
|
db.cached_file()
|
||||||
.cached_file()
|
.create(object_id, object_type, message_id, chat_id, vec![])
|
||||||
.create(
|
.exec()
|
||||||
object_id,
|
.await
|
||||||
object_type,
|
.unwrap(),
|
||||||
message_id,
|
|
||||||
chat_id,
|
|
||||||
vec![]
|
|
||||||
)
|
|
||||||
.exec()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn download_from_cache(
|
pub async fn download_from_cache(
|
||||||
cached_data: cached_file::Data,
|
cached_data: cached_file::Data,
|
||||||
db: Database
|
db: Database,
|
||||||
) -> Option<DownloadResult> {
|
) -> Option<DownloadResult> {
|
||||||
let response_task = tokio::task::spawn(download_from_telegram_files(cached_data.message_id, cached_data.chat_id));
|
let response_task = tokio::task::spawn(download_from_telegram_files(
|
||||||
let filename_task = tokio::task::spawn(get_filename(cached_data.object_id, cached_data.object_type.clone()));
|
cached_data.message_id,
|
||||||
|
cached_data.chat_id,
|
||||||
|
));
|
||||||
|
let filename_task = tokio::task::spawn(get_filename(
|
||||||
|
cached_data.object_id,
|
||||||
|
cached_data.object_type.clone(),
|
||||||
|
));
|
||||||
let book_task = tokio::task::spawn(get_book(cached_data.object_id));
|
let book_task = tokio::task::spawn(get_book(cached_data.object_id));
|
||||||
|
|
||||||
let response = match response_task.await.unwrap() {
|
let response = match response_task.await.unwrap() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
db.cached_file()
|
db.cached_file()
|
||||||
.delete(cached_file::object_id_object_type(cached_data.object_id, cached_data.object_type.clone()))
|
.delete(cached_file::object_id_object_type(
|
||||||
|
cached_data.object_id,
|
||||||
|
cached_data.object_type.clone(),
|
||||||
|
))
|
||||||
.exec()
|
.exec()
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
log::error!("{:?}", err);
|
log::error!("{:?}", err);
|
||||||
return None;
|
return None;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let filename_data = match filename_task.await.unwrap() {
|
let filename_data = match filename_task.await.unwrap() {
|
||||||
@@ -122,14 +128,17 @@ pub async fn download_from_cache(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let FilenameData {filename, filename_ascii} = filename_data;
|
let FilenameData {
|
||||||
|
filename,
|
||||||
|
filename_ascii,
|
||||||
|
} = filename_data;
|
||||||
let caption = book.get_caption();
|
let caption = book.get_caption();
|
||||||
|
|
||||||
Some(DownloadResult {
|
Some(DownloadResult {
|
||||||
response,
|
response,
|
||||||
filename,
|
filename,
|
||||||
filename_ascii,
|
filename_ascii,
|
||||||
caption
|
caption,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,13 +147,13 @@ pub struct FileLinkResult {
|
|||||||
pub link: String,
|
pub link: String,
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
pub filename_ascii: String,
|
pub filename_ascii: String,
|
||||||
pub caption: String
|
pub caption: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_download_link(
|
pub async fn get_download_link(
|
||||||
object_id: i32,
|
object_id: i32,
|
||||||
object_type: String,
|
object_type: String,
|
||||||
db: Database
|
db: Database,
|
||||||
) -> Result<Option<FileLinkResult>, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<Option<FileLinkResult>, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let cached_file = match get_cached_file_or_cache(object_id, object_type, db.clone()).await {
|
let cached_file = match get_cached_file_or_cache(object_id, object_type, db.clone()).await {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@@ -156,7 +165,12 @@ pub async fn get_download_link(
|
|||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let DownloadResult { mut response, filename, filename_ascii, caption } = data;
|
let DownloadResult {
|
||||||
|
mut response,
|
||||||
|
filename,
|
||||||
|
filename_ascii,
|
||||||
|
caption,
|
||||||
|
} = data;
|
||||||
|
|
||||||
let tempfile = match response_to_tempfile(&mut response).await {
|
let tempfile = match response_to_tempfile(&mut response).await {
|
||||||
Some(v) => v.0,
|
Some(v) => v.0,
|
||||||
@@ -172,11 +186,12 @@ pub async fn get_download_link(
|
|||||||
link,
|
link,
|
||||||
filename,
|
filename,
|
||||||
filename_ascii,
|
filename_ascii,
|
||||||
caption
|
caption,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_books_for_update() -> Result<Vec<BaseBook>, Box<dyn std::error::Error + Send + Sync>> {
|
pub async fn get_books_for_update(
|
||||||
|
) -> Result<Vec<BaseBook>, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let mut result: Vec<BaseBook> = vec![];
|
let mut result: Vec<BaseBook> = vec![];
|
||||||
|
|
||||||
let page_size = 50;
|
let page_size = 50;
|
||||||
@@ -187,12 +202,8 @@ pub async fn get_books_for_update() -> Result<Vec<BaseBook>, Box<dyn std::error:
|
|||||||
let uploaded_gte = subset_3.format("%Y-%m-%d").to_string();
|
let uploaded_gte = subset_3.format("%Y-%m-%d").to_string();
|
||||||
let uploaded_lte = now.format("%Y-%m-%d").to_string();
|
let uploaded_lte = now.format("%Y-%m-%d").to_string();
|
||||||
|
|
||||||
let first_page = match get_books(
|
let first_page = match get_books(1, page_size, uploaded_gte.clone(), uploaded_lte.clone()).await
|
||||||
1,
|
{
|
||||||
page_size,
|
|
||||||
uploaded_gte.clone(),
|
|
||||||
uploaded_lte.clone()
|
|
||||||
).await {
|
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
@@ -203,45 +214,51 @@ pub async fn get_books_for_update() -> Result<Vec<BaseBook>, Box<dyn std::error:
|
|||||||
let page_count = first_page.pages;
|
let page_count = first_page.pages;
|
||||||
|
|
||||||
while current_page <= page_count {
|
while current_page <= page_count {
|
||||||
let page = match get_books(current_page, page_size, uploaded_gte.clone(), uploaded_lte.clone()).await {
|
let page = match get_books(
|
||||||
|
current_page,
|
||||||
|
page_size,
|
||||||
|
uploaded_gte.clone(),
|
||||||
|
uploaded_lte.clone(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
result.extend(page.items);
|
result.extend(page.items);
|
||||||
|
|
||||||
current_page += 1;
|
current_page += 1;
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn start_update_cache(db: Database) {
|
||||||
pub async fn start_update_cache(
|
|
||||||
db: Database
|
|
||||||
) {
|
|
||||||
let books = match get_books_for_update().await {
|
let books = match get_books_for_update().await {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("{:?}", err);
|
log::error!("{:?}", err);
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for book in books {
|
for book in books {
|
||||||
'types: for available_type in book.available_types {
|
'types: for available_type in book.available_types {
|
||||||
let cached_file = match db
|
let cached_file = match db
|
||||||
.cached_file()
|
.cached_file()
|
||||||
.find_unique(
|
.find_unique(cached_file::object_id_object_type(
|
||||||
cached_file::object_id_object_type(book.id, available_type.clone())
|
book.id,
|
||||||
)
|
available_type.clone(),
|
||||||
|
))
|
||||||
.exec()
|
.exec()
|
||||||
.await {
|
.await
|
||||||
Ok(v) => v,
|
{
|
||||||
Err(err) => {
|
Ok(v) => v,
|
||||||
log::error!("{:?}", err);
|
Err(err) => {
|
||||||
continue 'types;
|
log::error!("{:?}", err);
|
||||||
}
|
continue 'types;
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if cached_file.is_some() {
|
if cached_file.is_some() {
|
||||||
continue 'types;
|
continue 'types;
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
use reqwest::{Response, multipart::{Form, Part}, header};
|
use reqwest::{
|
||||||
|
header,
|
||||||
|
multipart::{Form, Part},
|
||||||
|
Response,
|
||||||
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct UploadData {
|
pub struct UploadData {
|
||||||
pub chat_id: i64,
|
pub chat_id: i64,
|
||||||
pub message_id: i64
|
pub message_id: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct UploadResult {
|
pub struct UploadResult {
|
||||||
pub backend: String,
|
pub backend: String,
|
||||||
pub data: UploadData
|
pub data: UploadData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn download_from_telegram_files(
|
pub async fn download_from_telegram_files(
|
||||||
message_id: i64,
|
message_id: i64,
|
||||||
chat_id: i64
|
chat_id: i64,
|
||||||
) -> Result<Response, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<Response, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/api/v1/files/download_by_message/{chat_id}/{message_id}",
|
"{}/api/v1/files/download_by_message/{chat_id}/{message_id}",
|
||||||
@@ -38,15 +39,11 @@ pub async fn download_from_telegram_files(
|
|||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn upload_to_telegram_files(
|
pub async fn upload_to_telegram_files(
|
||||||
data_response: Response,
|
data_response: Response,
|
||||||
caption: String
|
caption: String,
|
||||||
) -> Result<UploadData, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<UploadData, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let url = format!(
|
let url = format!("{}/api/v1/files/upload/", CONFIG.files_url);
|
||||||
"{}/api/v1/files/upload/",
|
|
||||||
CONFIG.files_url
|
|
||||||
);
|
|
||||||
|
|
||||||
let headers = data_response.headers();
|
let headers = data_response.headers();
|
||||||
|
|
||||||
@@ -60,19 +57,14 @@ pub async fn upload_to_telegram_files(
|
|||||||
let base64_encoder = general_purpose::STANDARD;
|
let base64_encoder = general_purpose::STANDARD;
|
||||||
|
|
||||||
let filename = std::str::from_utf8(
|
let filename = std::str::from_utf8(
|
||||||
&base64_encoder
|
&base64_encoder
|
||||||
.decode(
|
.decode(headers.get("x-filename-b64-ascii").unwrap())
|
||||||
headers
|
.unwrap(),
|
||||||
.get("x-filename-b64-ascii")
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
)
|
.to_string();
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
let part = Part::stream(data_response)
|
let part = Part::stream(data_response).file_name(filename.clone());
|
||||||
.file_name(filename.clone());
|
|
||||||
|
|
||||||
let form = Form::new()
|
let form = Form::new()
|
||||||
.text("caption", caption)
|
.text("caption", caption)
|
||||||
@@ -90,8 +82,6 @@ pub async fn upload_to_telegram_files(
|
|||||||
|
|
||||||
match response.json::<UploadResult>().await {
|
match response.json::<UploadResult>().await {
|
||||||
Ok(v) => Ok(v.data),
|
Ok(v) => Ok(v.data),
|
||||||
Err(err) => {
|
Err(err) => Err(Box::new(err)),
|
||||||
Err(Box::new(err))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
108
src/views.rs
108
src/views.rs
@@ -1,13 +1,31 @@
|
|||||||
use axum::{Router, response::{Response, IntoResponse, AppendHeaders}, http::{StatusCode, self, Request, header}, middleware::{Next, self}, Extension, routing::{get, delete, post}, extract::Path, Json, body::StreamBody};
|
use axum::{
|
||||||
|
body::StreamBody,
|
||||||
|
extract::Path,
|
||||||
|
http::{self, header, Request, StatusCode},
|
||||||
|
middleware::{self, Next},
|
||||||
|
response::{AppendHeaders, IntoResponse, Response},
|
||||||
|
routing::{delete, get, post},
|
||||||
|
Extension, Json, Router,
|
||||||
|
};
|
||||||
use axum_prometheus::PrometheusMetricLayer;
|
use axum_prometheus::PrometheusMetricLayer;
|
||||||
use tokio_util::io::ReaderStream;
|
|
||||||
use tower_http::trace::{TraceLayer, self};
|
|
||||||
use tracing::{Level, log};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio_util::io::ReaderStream;
|
||||||
|
use tower_http::trace::{self, TraceLayer};
|
||||||
|
use tracing::{log, Level};
|
||||||
|
|
||||||
use crate::{config::CONFIG, db::get_prisma_client, prisma::{PrismaClient, cached_file::{self}}, services::{get_cached_file_or_cache, download_from_cache, download_utils::get_response_async_read, start_update_cache, get_download_link}};
|
use crate::{
|
||||||
|
config::CONFIG,
|
||||||
|
db::get_prisma_client,
|
||||||
|
prisma::{
|
||||||
|
cached_file::{self},
|
||||||
|
PrismaClient,
|
||||||
|
},
|
||||||
|
services::{
|
||||||
|
download_from_cache, download_utils::get_response_async_read, get_cached_file_or_cache,
|
||||||
|
get_download_link, start_update_cache,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub type Database = Arc<PrismaClient>;
|
pub type Database = Arc<PrismaClient>;
|
||||||
|
|
||||||
@@ -15,7 +33,7 @@ pub type Database = Arc<PrismaClient>;
|
|||||||
|
|
||||||
async fn get_cached_file(
|
async fn get_cached_file(
|
||||||
Path((object_id, object_type)): Path<(i32, String)>,
|
Path((object_id, object_type)): Path<(i32, String)>,
|
||||||
Extension(Ext { db, .. }): Extension<Ext>
|
Extension(Ext { db, .. }): Extension<Ext>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
match get_cached_file_or_cache(object_id, object_type, db).await {
|
match get_cached_file_or_cache(object_id, object_type, db).await {
|
||||||
Some(cached_file) => Json(cached_file).into_response(),
|
Some(cached_file) => Json(cached_file).into_response(),
|
||||||
@@ -25,20 +43,22 @@ async fn get_cached_file(
|
|||||||
|
|
||||||
async fn download_cached_file(
|
async fn download_cached_file(
|
||||||
Path((object_id, object_type)): Path<(i32, String)>,
|
Path((object_id, object_type)): Path<(i32, String)>,
|
||||||
Extension(Ext { db }): Extension<Ext>
|
Extension(Ext { db }): Extension<Ext>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let cached_file = match get_cached_file_or_cache(object_id, object_type.clone(), db.clone()).await {
|
let cached_file =
|
||||||
Some(cached_file) => cached_file,
|
match get_cached_file_or_cache(object_id, object_type.clone(), db.clone()).await {
|
||||||
None => return StatusCode::NO_CONTENT.into_response(),
|
Some(cached_file) => cached_file,
|
||||||
};
|
None => return StatusCode::NO_CONTENT.into_response(),
|
||||||
|
};
|
||||||
|
|
||||||
let data = match download_from_cache(cached_file, db.clone()).await {
|
let data = match download_from_cache(cached_file, db.clone()).await {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
let cached_file = match get_cached_file_or_cache(object_id, object_type, db.clone()).await {
|
let cached_file =
|
||||||
Some(v) => v,
|
match get_cached_file_or_cache(object_id, object_type, db.clone()).await {
|
||||||
None => return StatusCode::NO_CONTENT.into_response(),
|
Some(v) => v,
|
||||||
};
|
None => return StatusCode::NO_CONTENT.into_response(),
|
||||||
|
};
|
||||||
|
|
||||||
match download_from_cache(cached_file, db).await {
|
match download_from_cache(cached_file, db).await {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@@ -68,8 +88,8 @@ async fn download_cached_file(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
header::HeaderName::from_static("x-caption-b64"),
|
header::HeaderName::from_static("x-caption-b64"),
|
||||||
encoder.encode(caption)
|
encoder.encode(caption),
|
||||||
)
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
(headers, body).into_response()
|
(headers, body).into_response()
|
||||||
@@ -77,28 +97,30 @@ async fn download_cached_file(
|
|||||||
|
|
||||||
async fn get_link(
|
async fn get_link(
|
||||||
Path((object_id, object_type)): Path<(i32, String)>,
|
Path((object_id, object_type)): Path<(i32, String)>,
|
||||||
Extension(Ext { db, .. }): Extension<Ext>
|
Extension(Ext { db, .. }): Extension<Ext>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
match get_download_link(object_id, object_type.clone(), db.clone()).await {
|
match get_download_link(object_id, object_type.clone(), db.clone()).await {
|
||||||
Ok(data) => {
|
Ok(data) => match data {
|
||||||
match data {
|
Some(data) => Json(data).into_response(),
|
||||||
Some(data) => Json(data).into_response(),
|
None => StatusCode::NO_CONTENT.into_response(),
|
||||||
None => StatusCode::NO_CONTENT.into_response(),
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("{:?}", err);
|
log::error!("{:?}", err);
|
||||||
StatusCode::NO_CONTENT.into_response()
|
StatusCode::NO_CONTENT.into_response()
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_cached_file(
|
async fn delete_cached_file(
|
||||||
Path((object_id, object_type)): Path<(i32, String)>,
|
Path((object_id, object_type)): Path<(i32, String)>,
|
||||||
Extension(Ext { db, .. }): Extension<Ext>
|
Extension(Ext { db, .. }): Extension<Ext>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let cached_file = db.cached_file()
|
let cached_file = db
|
||||||
.find_unique(cached_file::object_id_object_type(object_id, object_type.clone()))
|
.cached_file()
|
||||||
|
.find_unique(cached_file::object_id_object_type(
|
||||||
|
object_id,
|
||||||
|
object_type.clone(),
|
||||||
|
))
|
||||||
.exec()
|
.exec()
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -112,14 +134,12 @@ async fn delete_cached_file(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Json(v).into_response()
|
Json(v).into_response()
|
||||||
},
|
}
|
||||||
None => StatusCode::NOT_FOUND.into_response(),
|
None => StatusCode::NOT_FOUND.into_response(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_cache(
|
async fn update_cache(Extension(Ext { db, .. }): Extension<Ext>) -> impl IntoResponse {
|
||||||
Extension(Ext { db, .. }): Extension<Ext>
|
|
||||||
) -> impl IntoResponse {
|
|
||||||
tokio::spawn(start_update_cache(db));
|
tokio::spawn(start_update_cache(db));
|
||||||
|
|
||||||
StatusCode::OK.into_response()
|
StatusCode::OK.into_response()
|
||||||
@@ -127,9 +147,9 @@ async fn update_cache(
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
async fn auth<B>(req: Request<B>, next: Next<B>) -> Result<Response, StatusCode> {
|
async fn auth<B>(req: Request<B>, next: Next<B>) -> Result<Response, StatusCode> {
|
||||||
let auth_header = req.headers()
|
let auth_header = req
|
||||||
|
.headers()
|
||||||
.get(http::header::AUTHORIZATION)
|
.get(http::header::AUTHORIZATION)
|
||||||
.and_then(|header| header.to_str().ok());
|
.and_then(|header| header.to_str().ok());
|
||||||
|
|
||||||
@@ -146,13 +166,11 @@ async fn auth<B>(req: Request<B>, next: Next<B>) -> Result<Response, StatusCode>
|
|||||||
Ok(next.run(req).await)
|
Ok(next.run(req).await)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Ext {
|
struct Ext {
|
||||||
pub db: Arc<PrismaClient>,
|
pub db: Arc<PrismaClient>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn get_router() -> Router {
|
pub async fn get_router() -> Router {
|
||||||
let db = Arc::new(get_prisma_client().await);
|
let db = Arc::new(get_prisma_client().await);
|
||||||
|
|
||||||
@@ -162,26 +180,26 @@ pub async fn get_router() -> Router {
|
|||||||
|
|
||||||
let app_router = Router::new()
|
let app_router = Router::new()
|
||||||
.route("/:object_id/:object_type/", get(get_cached_file))
|
.route("/:object_id/:object_type/", get(get_cached_file))
|
||||||
.route("/download/:object_id/:object_type/", get(download_cached_file))
|
.route(
|
||||||
|
"/download/:object_id/:object_type/",
|
||||||
|
get(download_cached_file),
|
||||||
|
)
|
||||||
.route("/link/:object_id/:object_type/", get(get_link))
|
.route("/link/:object_id/:object_type/", get(get_link))
|
||||||
.route("/:object_id/:object_type/", delete(delete_cached_file))
|
.route("/:object_id/:object_type/", delete(delete_cached_file))
|
||||||
.route("/update_cache", post(update_cache))
|
.route("/update_cache", post(update_cache))
|
||||||
|
|
||||||
.layer(middleware::from_fn(auth))
|
.layer(middleware::from_fn(auth))
|
||||||
.layer(Extension(ext))
|
.layer(Extension(ext))
|
||||||
.layer(prometheus_layer);
|
.layer(prometheus_layer);
|
||||||
|
|
||||||
let metric_router = Router::new()
|
let metric_router =
|
||||||
.route("/metrics", get(|| async move { metric_handle.render() }));
|
Router::new().route("/metrics", get(|| async move { metric_handle.render() }));
|
||||||
|
|
||||||
Router::new()
|
Router::new()
|
||||||
.nest("/api/v1/", app_router)
|
.nest("/api/v1/", app_router)
|
||||||
.nest("/", metric_router)
|
.nest("/", metric_router)
|
||||||
.layer(
|
.layer(
|
||||||
TraceLayer::new_for_http()
|
TraceLayer::new_for_http()
|
||||||
.make_span_with(trace::DefaultMakeSpan::new()
|
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
|
||||||
.level(Level::INFO))
|
.on_response(trace::DefaultOnResponse::new().level(Level::INFO)),
|
||||||
.on_response(trace::DefaultOnResponse::new()
|
|
||||||
.level(Level::INFO)),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user