Skip to content

Commit 3321e83

Browse files
author
amateurforger
committed
WIP
1 parent 91cecac commit 3321e83

File tree

9 files changed

+663
-592
lines changed

9 files changed

+663
-592
lines changed

Cargo.lock

Lines changed: 581 additions & 537 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ env_logger = "0.11.8"
3636
# Interactions with the torrent client
3737
# Comment/uncomment below for development version
3838
# hightorrent_api = { path = "../hightorrent_api" }
39-
hightorrent_api = { git = "https://github.com/angrynode/hightorrent_api" }
39+
hightorrent_api = { git = "https://github.com/angrynode/hightorrent_api", branch = "feat-sea-orm", features = [ "sea_orm" ]}
4040
# hightorrent_api = "0.2"
4141
log = "0.4.27"
42-
# SQLite ORM
43-
sea-orm = { version = "2.0.0-rc.18", features = [ "runtime-tokio", "debug-print", "sqlx-sqlite"] }
42+
# SQLite ORM (latest RC is broken)
43+
# sea-orm = { git = "https://github.com/SeaQL/sea-orm/", features = [ "runtime-tokio", "debug-print", "sqlx-sqlite"] }
44+
sea-orm = { version = "=2.0.0-rc.28", features = [ "runtime-tokio", "debug-print", "sqlx-sqlite"] }
4445
# SQLite migrations
45-
sea-orm-migration = { version = "2.0.0-rc.18" }
46+
sea-orm-migration = { version = "=2.0.0-rc.28" }
47+
# sea-orm-migration = { git = "https://github.com/SeaQL/sea-orm" }
4648
# Serialization/deserialization, for example in path extractors
4749
serde = { version = "1.0.219", features = ["derive", "rc"] }
4850
# (De)serialization for operations log

src/database/magnet.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use chrono::Utc;
2-
use hightorrent_api::hightorrent::{MagnetLink, MagnetLinkError};
2+
use hightorrent_api::hightorrent::{MagnetLink, MagnetLinkError, TorrentID};
33
use sea_orm::entity::prelude::*;
44
use sea_orm::*;
55
use snafu::prelude::*;
@@ -21,8 +21,8 @@ use crate::state::logger::LoggerError;
2121
pub struct Model {
2222
#[sea_orm(primary_key)]
2323
pub id: i32,
24-
pub torrent_id: String,
25-
pub magnet: String,
24+
pub torrent_id: TorrentID,
25+
pub magnet: MagnetLink,
2626
pub name: String,
2727
pub resolved: bool,
2828
}
@@ -72,7 +72,7 @@ impl MagnetOperator {
7272
}
7373

7474
/// Delete an uploaded magnet
75-
pub async fn delete(&self, id: i32, user: Option<User>) -> Result<String, MagnetError> {
75+
pub async fn delete(&self, id: i32) -> Result<String, MagnetError> {
7676
let db = &self.state.database;
7777

7878
let uploaded_magnet = Entity::find_by_id(id)
@@ -85,7 +85,7 @@ impl MagnetOperator {
8585
uploaded_magnet.delete(db).await.context(DBSnafu)?;
8686

8787
let operation_log = OperationLog {
88-
user,
88+
user: self.user.clone(),
8989
date: Utc::now(),
9090
table: Table::Magnet,
9191
operation: OperationType::Delete,
@@ -110,21 +110,21 @@ impl MagnetOperator {
110110
/// Fails if:
111111
///
112112
/// - the magnet is invalid
113-
pub async fn create(&self, f: &MagnetForm, user: Option<User>) -> Result<Model, MagnetError> {
113+
pub async fn create(&self, f: &MagnetForm) -> Result<Model, MagnetError> {
114114
let magnet = MagnetLink::new(&f.magnet).context(InvalidMagnetSnafu)?;
115115

116116
// Check duplicates
117117
let list = self.list().await?;
118118

119-
if list.iter().any(|x| x.torrent_id == magnet.id().as_str()) {
119+
if list.iter().any(|x| x.torrent_id == magnet.id()) {
120120
return Err(MagnetError::TorrentIDTaken {
121121
torrent_id: magnet.id().to_string(),
122122
});
123123
}
124124

125125
let model = ActiveModel {
126-
torrent_id: Set(magnet.id().to_string()),
127-
magnet: Set(magnet.to_string()),
126+
torrent_id: Set(magnet.id()),
127+
magnet: Set(magnet.clone()),
128128
name: Set(magnet.name().to_string()),
129129
// TODO: check if we already have the torrent in which case it's already resolved!
130130
resolved: Set(false),
@@ -138,7 +138,7 @@ impl MagnetOperator {
138138
let model = model.try_into_model().unwrap();
139139

140140
let operation_log = OperationLog {
141-
user,
141+
user: self.user.clone(),
142142
date: Utc::now(),
143143
table: Table::Magnet,
144144
operation: OperationType::Create,

src/routes/index.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ pub struct IndexTemplate {
2222
/// Magnet upload form
2323
pub post: Option<MagnetForm>,
2424
/// Error with submitted magnet
25-
/// TODO: typed error
26-
pub post_error: Option<String>,
25+
pub post_error: Option<AppStateError>,
2726
}
2827

2928
impl IndexTemplate {
@@ -45,7 +44,7 @@ impl IndexTemplate {
4544
})
4645
}
4746

48-
pub fn with_errored_form(mut self, form: MagnetForm, error: String) -> Self {
47+
pub fn with_errored_form(mut self, form: MagnetForm, error: AppStateError) -> Self {
4948
self.post = Some(form);
5049
self.post_error = Some(error);
5150
self

src/routes/magnet.rs

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use askama::Template;
22
use askama_web::WebTemplate;
3-
use axum::extract::{Multipart, State};
4-
use axum::response::{IntoResponse, Redirect};
3+
use axum::extract::{Form, State};
4+
use axum::response::{IntoResponse, Response};
55
use hightorrent_api::hightorrent::MagnetLink;
66
use serde::{Deserialize, Serialize};
7+
use snafu::prelude::*;
78

9+
use crate::database::magnet::{MagnetOperator, Model as Magnet};
810
use crate::extractors::user::User;
911
use crate::routes::index::IndexTemplate;
10-
use crate::state::{AppState, AppStateContext, error::AppStateError};
12+
use crate::state::{AppState, AppStateContext, error::*};
1113

1214
/// Multipart form submitted to /magnet/upload:
1315
///
@@ -31,42 +33,44 @@ pub struct MagnetTemplate {
3133
pub async fn upload(
3234
State(app_state): State<AppState>,
3335
user: Option<User>,
34-
mut form: Multipart,
35-
) -> Result<impl IntoResponse, AppStateError> {
36-
let mut magnet: Option<String> = None;
37-
38-
while let Some(field) = form.next_field().await.unwrap() {
39-
let name = field.name().unwrap().to_string();
40-
let data = field.text().await.unwrap();
41-
42-
if name == "magnet" && !data.is_empty() {
43-
magnet = Some(data);
44-
}
45-
}
46-
47-
if magnet.is_none() {
48-
// No magnet was submitted. This is not an error, simply display the form again
49-
return Ok(Redirect::to("/").into_response());
50-
}
51-
52-
let magnet = magnet.unwrap();
53-
36+
Form(form): Form<MagnetForm>,
37+
) -> Result<Response, AppStateError> {
5438
// Parse magnet
55-
match MagnetLink::new(&magnet) {
56-
Ok(magnet) => Ok(MagnetTemplate {
39+
let operator = MagnetOperator::new(app_state.clone(), user.clone());
40+
41+
match operator.create(&form).await.context(MagnetUploadSnafu) {
42+
Ok(magnet_model) => Ok(MagnetTemplate {
5743
state: app_state.context().await?,
5844
user,
59-
magnet,
45+
magnet: magnet_model.magnet,
6046
}
6147
.into_response()),
62-
Err(e) => {
63-
let form = MagnetForm { magnet };
64-
65-
// TODO: typed error
66-
Ok(IndexTemplate::new(app_state, user)
67-
.await?
68-
.with_errored_form(form, e.to_string())
69-
.into_response())
70-
}
48+
Err(e) => Ok(IndexTemplate::new(app_state, user)
49+
.await?
50+
.with_errored_form(form, e)
51+
.into_response()),
7152
}
7253
}
54+
55+
#[derive(Template, WebTemplate)]
56+
#[template(path = "magnet_list.html")]
57+
pub struct MagnetListTemplate {
58+
/// Global application state (errors/warnings)
59+
pub state: AppStateContext,
60+
/// Logged-in user.
61+
pub user: Option<User>,
62+
/// Magnets stored in database
63+
pub magnets: Vec<Magnet>,
64+
}
65+
66+
// pub async fn list(
67+
// State(app_state): State<AppState>,
68+
// user: Option<User>
69+
// ) -> Result<impl IntoResponse, AppStateError> {
70+
71+
// Ok(MagnetTemplate {
72+
// state: app_state.context().await?,
73+
// user,
74+
// magnet,
75+
// })
76+
// }

src/state/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ pub enum AppStateError {
3131
Category { source: CategoryError },
3232
#[snafu(display("Error during migration"))]
3333
Migration { source: MigrationError },
34+
#[snafu(display("Magnet upload error"))]
35+
MagnetUpload {
36+
source: crate::database::magnet::MagnetError,
37+
},
3438
}
3539

3640
impl AppStateError {

templates/index.html

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,15 @@ <h1>Download files</h1>
1111
{% endif %}
1212

1313
{% if let Some(error) = post_error %}
14-
<div class="alert alert-danger mt-4">
15-
<p class="mb-0">{{ error }}</p>
14+
<div class="notification is-danger alert alert-danger">
15+
<details>
16+
<summary>{{ error }}</summary>
17+
<ul class="ml-5">
18+
{% for inner_error in error.inner_errors() %}
19+
<li>→ {{ inner_error }}</li>
20+
{% endfor %}
21+
</ul>
22+
</details>
1623
</div>
1724
{% endif %}
1825

@@ -69,5 +76,9 @@ <h1 class="modal-title fs-5" id="staticBackdropLabel">Oops, you don't have any c
6976
});
7077
</script>
7178
{% endif %}
79+
<div class="card mt-4">
80+
<div class="card-body">
81+
</div>
82+
</div>
7283
</div>
7384
{% endblock %}

templates/magnet_list.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{% extends "base.html" %}
2+
3+
{% block main %}
4+
<div class="card mb-4">
5+
<h2>List of uploaded magnets not yet resolved</h2>
6+
</div>
7+
{% endblock main %}

templates/sources/magnet.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ <h2 class="text-center">
44
<label for="magnet">Magnet link</label>
55
</h2>
66

7-
<form method="POST" action="/magnet/upload" enctype="multipart/form-data" accept-charset="utf-8">
7+
<form method="POST" action="/magnet/upload" accept-charset="utf-8">
88
<div class="row align-items-center">
99
<div class="col-md-3 text-center">
1010
<img src="/assets/images/magnet.png" class="img-64">

0 commit comments

Comments
 (0)