draft new ggemini api version

This commit is contained in:
yggverse 2024-10-25 03:34:17 +03:00
parent ca22d9b315
commit 2cc69288fb

View File

@ -14,15 +14,12 @@ use widget::Widget;
use meta::{Meta, Status}; use meta::{Meta, Status};
use gtk::{ use gtk::{
gio::{Cancellable, SimpleAction, SocketClient, SocketProtocol, TlsCertificateFlags}, gio::{Cancellable, SimpleAction},
glib::{ glib::{
gformat, uuid_string_random, GString, Priority, Regex, RegexCompileFlags, RegexMatchFlags, gformat, uuid_string_random, GString, Priority, Regex, RegexCompileFlags, RegexMatchFlags,
Uri, UriFlags, Uri, UriFlags,
}, },
prelude::{ prelude::{ActionExt, StaticVariantType, ToVariant},
ActionExt, IOStreamExt, OutputStreamExtManual, SocketClientExt, StaticVariantType,
ToVariant,
},
Box, Box,
}; };
use sqlite::Transaction; use sqlite::Transaction;
@ -191,108 +188,58 @@ impl Page {
"gemini" => { "gemini" => {
// Define local NS // Define local NS
use gemini::client::{ use gemini::client::{
connection::Input, request_async,
response::{ response::header::{Mime as ResponseMime, Status as ResponseStatus},
header::{Mime as ResponseMime, Status as ResponseStatus},
Response,
},
}; };
// Get host
let host = match uri.host() {
Some(host) => host,
None => todo!(),
};
// Update
meta.borrow_mut().status = Some(Status::Prepare);
meta.borrow_mut().description = Some(gformat!("Connect {host}.."));
action_update.activate(Some(&id));
// Create new connection
let cancellable = Cancellable::new();
let client = SocketClient::new();
client.set_timeout(10);
client.set_tls(true);
client.set_tls_validation_flags(TlsCertificateFlags::INSECURE);
client.set_protocol(SocketProtocol::Tcp);
client.connect_to_uri_async(
&uri.to_str(),
1965,
Some(&cancellable.clone()),
move |result| match result {
Ok(connection) => {
// Update
meta.borrow_mut().status = Some(Status::Connect);
meta.borrow_mut().description = Some(gformat!("Connected to {host}.."));
action_update.activate(Some(&id));
// Send request
connection.output_stream().write_all_async(
gformat!("{}\r\n", &uri.to_str()),
Priority::DEFAULT,
Some(&cancellable.clone()),
move |o| match o {
Ok(_) => {
// Update page status // Update page status
meta.borrow_mut().status = Some(Status::Request); meta.borrow_mut().status = Some(Status::Prepare);
meta.borrow_mut().description = Some(gformat!("Request data from {host}..")); meta.borrow_mut().description = Some(gformat!("Connect.."));
action_update.activate(Some(&id)); action_update.activate(Some(&id));
// Create new byte buffer and read server response // Begin request
Input::new_from_stream( request_async(
connection.input_stream() uri.clone(),
).read_all_async( Some(Cancellable::new()),
Some(cancellable.clone()), Some(Priority::DEFAULT),
None, move |result| match result {
None,
move |i| {
match i {
Ok(buffer) => {
match Response::from_utf8(
&buffer.to_utf8(),
) {
Ok(response) => { Ok(response) => {
// Format response // Format response
meta.borrow_mut().status = Some(Status::Response); meta.borrow_mut().status = Some(Status::Response);
meta.borrow_mut().description = Some(host);
meta.borrow_mut().title = uri.host(); meta.borrow_mut().title = uri.host();
action_update.activate(Some(&id)); action_update.activate(Some(&id));
match response.header().status() { match response.header().status() {
// 10 | 11 // 10 | 11
Some(ResponseStatus::Input) | Some(ResponseStatus::SensitiveInput) => { Some(ResponseStatus::Input)
| Some(ResponseStatus::SensitiveInput) => {
// Format response // Format response
let status = Status::Input; let status = Status::Input;
let title = gformat!("Input expected"); let title = gformat!("Input expected");
let description = match response.header().meta() { let description = match response.header().meta() {
Some(meta) => match meta.to_gstring() { Some(meta) => match meta.to_gstring() {
Ok(value) => value, Ok(value) => value,
Err(_) => title.clone() Err(_) => title.clone(),
}, },
None => title.clone(), None => title.clone(),
}; };
// Make input form // Make input form
match response.header().status() { match response.header().status() {
Some(ResponseStatus::SensitiveInput) => Some(ResponseStatus::SensitiveInput) => input
input.set_new_sensitive( .set_new_sensitive(
action_page_open, uri, action_page_open,
uri,
Some(&description), Some(&description),
Some(1024), Some(1024),
), ),
_ => _ => input.set_new_response(
input.set_new_response( action_page_open,
action_page_open, uri, uri,
Some(&description), Some(&description),
Some(1024), Some(1024),
) ),
} }
// Update meta // Update meta
@ -302,18 +249,22 @@ impl Page {
// Update page // Update page
action_update.activate(Some(&id)); action_update.activate(Some(&id));
}, }
// 20 // 20
Some(ResponseStatus::Success) => Some(ResponseStatus::Success) => match response
match response.header().mime() { .header()
.mime()
{
Some(ResponseMime::TextGemini) => { Some(ResponseMime::TextGemini) => {
// Update data // Update data
match response.body().to_gstring() { match response.body().to_gstring() {
Ok(source) => { Ok(source) => {
meta.borrow_mut().status = Some(Status::Success); meta.borrow_mut().status =
Some(Status::Success);
// This content type may return parsed title // This content type may return parsed title
meta.borrow_mut().title = content.set_text_gemini(&uri, &source); meta.borrow_mut().title =
content.set_text_gemini(&uri, &source);
// Add new history record // Add new history record
let request = uri.to_str(); let request = uri.to_str();
@ -329,17 +280,20 @@ impl Page {
// Update window components // Update window components
action_update.activate(Some(&id)); action_update.activate(Some(&id));
}, }
Err(_) => todo!(), Err(_) => todo!(),
} }
}, }
Some(ResponseMime::TextPlain) => { Some(ResponseMime::TextPlain) => {
meta.borrow_mut().status = Some(Status::Success); meta.borrow_mut().status = Some(Status::Success);
action_update.activate(Some(&id)); action_update.activate(Some(&id));
todo!() todo!()
}, }
Some(ResponseMime::ImagePng) | Some(ResponseMime::ImageGif) | Some(ResponseMime::ImageJpeg) | Some(ResponseMime::ImageWebp) => { Some(ResponseMime::ImagePng)
| Some(ResponseMime::ImageGif)
| Some(ResponseMime::ImageJpeg)
| Some(ResponseMime::ImageWebp) => {
// Update meta // Update meta
meta.borrow_mut().status = Some(Status::Success); meta.borrow_mut().status = Some(Status::Success);
meta.borrow_mut().title = Some(gformat!("Picture")); // @TODO meta.borrow_mut().title = Some(gformat!("Picture")); // @TODO
@ -361,15 +315,19 @@ impl Page {
// Update window components // Update window components
action_update.activate(Some(&id)); action_update.activate(Some(&id));
}, }
_ => { _ => {
// Define common data // Define common data
let status = Status::Failure; let status = Status::Failure;
let title = gformat!("Oops"); let title = gformat!("Oops");
let description = gformat!("Content type not supported"); let description =
gformat!("Content type not supported");
// Update widget // Update widget
content.set_status_failure(title.as_str(), description.as_str()); content.set_status_failure(
title.as_str(),
description.as_str(),
);
// Update meta // Update meta
meta.borrow_mut().status = Some(status); meta.borrow_mut().status = Some(status);
@ -378,7 +336,7 @@ impl Page {
// Update window // Update window
action_update.activate(Some(&id)); action_update.activate(Some(&id));
}, }
}, },
// 32 // 32
Some(ResponseStatus::Redirect) => { Some(ResponseStatus::Redirect) => {
@ -402,10 +360,10 @@ impl Page {
} }
) )
); );
}, }
None => todo!(), None => todo!(),
} }
}, }
// @TODO // @TODO
None => { None => {
// Define common data // Define common data
@ -414,7 +372,10 @@ impl Page {
let description = gformat!("Status code not supported"); let description = gformat!("Status code not supported");
// Update widget // Update widget
content.set_status_failure(title.as_str(), description.as_str()); content.set_status_failure(
title.as_str(),
description.as_str(),
);
// Update meta // Update meta
meta.borrow_mut().status = Some(status); meta.borrow_mut().status = Some(status);
@ -423,92 +384,18 @@ impl Page {
// Update window // Update window
action_update.activate(Some(&id)); action_update.activate(Some(&id));
}, }
}; };
} }
Err(_) => { Err(_) => {
// Define common data // Define common data
let status = Status::Failure; let status = Status::Failure;
let title = gformat!("Oops"); let title = gformat!("Oops");
let description = gformat!("Failed to read buffer data"); let description = gformat!("Failed to request");
// Update widget // Update widget
content.set_status_failure(title.as_str(), description.as_str()); content
.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
}
}
// Close connection
if let Err(error) = connection.close(Some(&cancellable)) {
todo!("Error closing connection: {}", error.message());
}
}
Err(_) => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Failed to read response");
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
// Close connection
if let Err(error) = connection.close(Some(&cancellable)) {
todo!("Error closing response connection: {}", error.message());
}
}
}
},
);
}
Err(error) => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Failed to read request: {}", error.1.message());
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
// Update meta
meta.borrow_mut().status = Some(status);
meta.borrow_mut().title = Some(title);
meta.borrow_mut().description = Some(description);
// Update window
action_update.activate(Some(&id));
// Close connection
if let Err(error) = connection.close(Some(&cancellable)) {
todo!("Error closing request connection: {}", error.message());
}
}
},
);
}
Err(error) => {
// Define common data
let status = Status::Failure;
let title = gformat!("Oops");
let description = gformat!("Failed to connect: {}", error.message());
// Update widget
content.set_status_failure(title.as_str(), description.as_str());
// Update meta // Update meta
meta.borrow_mut().status = Some(status); meta.borrow_mut().status = Some(status);