Initial commit

This commit is contained in:
2023-04-03 11:24:19 +01:00
commit d1f8ed7add
4 changed files with 734 additions and 0 deletions

100
src/main.rs Normal file
View File

@@ -0,0 +1,100 @@
extern crate cookie_store;
extern crate mail_builder;
extern crate subprocess;
extern crate ureq;
// Looking for <a href="https://morningstaronline.co.uk/system/files/pdf-editions/*.pdf">
// A failure here is probably due to login failing silently
fn get_link(agent: ureq::Agent) -> Option<String> {
let editions_rsp = agent
.get("https://morningstaronline.co.uk/digital-edition")
.call()
.expect("Failed to request list of PDF editions");
let body = editions_rsp
.into_string()
.expect("Couldn't read list of PDF editions");
if let Some(start_idx) =
body.find(r#"<a href="https://morningstaronline.co.uk/system/files/pdf-editions/"#)
{
let link = &body[start_idx + 9..];
if let Some(end_idx) = link.find('\"') {
return Some(link[..end_idx].to_owned());
}
}
None
}
fn main() {
let mut args = std::env::args().skip(1);
let to: String = args.next().expect("Provide To: on the command line");
let bcc: Vec<String> = args.collect();
let username = std::env::var("MS_USER").expect("Please set MS_USER envvar");
let password = std::env::var("MS_PASS").expect("Please set MS_PASS envvar");
let cookies = cookie_store::CookieStore::load_json(std::io::empty()).unwrap();
let agent = ureq::builder().cookie_store(cookies).build();
println!("Logging in...");
agent
.post("https://morningstaronline.co.uk/user/login?current=home")
.send_form(&[
("name", &username),
("pass", &password),
("form_id", "user_login"),
])
.expect("Failed to log in");
println!("Getting link to most recent PDF...");
let link = get_link(agent.clone()).expect("Couldn't get link to PDF edition");
let (_, filename) = link
.rsplit_once('/')
.expect("Couldn't parse filename from link");
let mut buf: Vec<u8> = vec![];
{
println!("Downloading PDF...");
agent
.get(&link)
.call()
.expect("Couldn't download digital edition")
.into_reader()
.read_to_end(&mut buf) // TODO: would be better to stream the bytes
.expect("Couldn't read bytes from server");
std::fs::write(filename, &buf).expect("Couldn't create file");
}
println!("Sending email...");
let mut sendmail = subprocess::Popen::create(
&["sendmail", "-t"],
subprocess::PopenConfig {
stdin: subprocess::Redirection::Pipe,
..Default::default()
},
)
.expect("Failed to launch sendmail");
let eml = mail_builder::MessageBuilder::new()
.to(vec![("Paper Round Comrade", to.as_str())])
.from(("Paper Round Comrade", to.as_str()))
.bcc(vec![("Valued Comrade", bcc)])
.subject("Morning Star delivery")
.text_body("Enjoy your paper")
.binary_attachment("application/pdf", filename, &buf)
.write_to_vec() // TODO: would be better to stream the bytes
.expect("Failed to generate email");
sendmail
.communicate_bytes(Some(&eml))
.expect("Failed to send email to sendmail");
sendmail.wait().expect("Sendmail execution failed");
println!("OK!");
}