use crate::*;
use alux_ext::ext;
use anyhow::{Result, bail};
const LAW_STATUS: &str = "1234567890123456789";
#[ext(name = XLaws)]
pub impl<This> This
where
This: XRequestAlg + XRequestViewAlg,
{
fn x_laws(&self) -> Result<()> {
self.check_address_laws()?;
self.check_request_laws()?;
check_taking_laws()
}
fn check_address_laws(&self) -> Result<()> {
for host in X_HOSTS {
for shape in [
format!("https://{host}/somebody/status/{LAW_STATUS}"),
format!("http://{host}/somebody/status/{LAW_STATUS}"),
format!("https://{host}/somebody/statuses/{LAW_STATUS}"),
format!("https://{host}/somebody/status/{LAW_STATUS}?s=20&t=abc"),
format!("https://{host}/somebody/status/{LAW_STATUS}/photo/1"),
format!(" https://{host}/somebody/status/{LAW_STATUS} "),
] {
if status_id(&shape).as_deref() != Some(LAW_STATUS) {
bail!("{shape} does not name the tweet it addresses");
}
}
}
for shape in [
"https://example.test/somebody/status/1234567890123456789",
"https://x.com/somebody",
"https://x.com/somebody/status/",
"https://x.com/somebody/status/not-a-number",
"https://x.com.example.test/somebody/status/1234567890123456789",
"/home/dev/x.com/somebody/status/1234567890123456789",
"https://www.youtube.com/watch?v=VIDEO_ID",
] {
if let Some(named) = status_id(shape) {
bail!("{shape} names the tweet {named}, and addresses no tweet");
}
}
Ok(())
}
fn check_request_laws(&self) -> Result<()> {
let asked = self.status_request(LAW_STATUS);
let asked_again = self.status_request(LAW_STATUS);
let address = self.request_address(&asked).to_owned();
if address != self.request_address(&asked_again) {
bail!("asking twice about one tweet asks two different things");
}
if !address.starts_with(READING_ADDRESS) {
bail!("a tweet is asked about somewhere other than where tweets are read");
}
if !address.contains(&format!("id={LAW_STATUS}")) {
bail!("asking about a tweet does not name which tweet");
}
let stated = reading_token(LAW_STATUS);
if stated.is_empty() || !address.contains(&format!("token={stated}")) {
bail!("asking about a tweet carries no token");
}
if reading_token("1") == reading_token("2") {
bail!("two tweets are asked about with one token");
}
Ok(())
}
}
fn check_taking_laws() -> Result<()> {
for (place, way) in take::ALL.iter().copied().enumerate() {
let named = take::to(way);
if take::ALL[..place]
.iter()
.any(|earlier| take::to(*earlier) == named)
{
bail!("two ways of taking are named {named}");
}
if take::from(named) != Some(way) {
bail!("{named} is not read back as itself");
}
if way.summary().is_empty() {
bail!("{named} does not say what it does");
}
}
if take::from("nothing anybody would call a way of taking").is_some() {
bail!("a word naming no way of taking names one");
}
for kind in attachment_kind::ALL.iter().copied() {
if !Take::Everything.accepts(kind) {
bail!(
"taking everything leaves {} behind",
attachment_kind::to(kind)
);
}
let ways = [Take::Videos, Take::Images]
.into_iter()
.filter(|way| way.accepts(kind))
.count();
if ways != 1 {
bail!(
"{} is taken by {ways} ways rather than one",
attachment_kind::to(kind)
);
}
if attachment_kind::from(attachment_kind::to(kind)) != Some(kind) {
bail!("{} is not read back as itself", attachment_kind::to(kind));
}
}
Ok(())
}