Salta al contenuto principale




Ustica è una questione morale. E civica


@Giornalismo e disordine informativo
articolo21.org/2025/11/ustica-…
Nei giorni scorsi abbiamo promosso, insieme con l’Associazione dei familiari delle vittime della strage di Ustica e la Presidente Daria Bonfietti un incontro-stampa per chiedere di non archiviare le indagini. Per la prima volta a livello nazionale, a






Un server ActivityPub in un singolo file PHP? Ecco come fare... Il post di @tofeo

Qualsiasi programma per computer può essere progettato per essere eseguito da un singolo file, se la progettazione è abbastanza sbagliata! 🤣

Volevo creare il server #Fediverse più semplice possibile, che potesse essere utilizzato come strumento didattico per mostrare come funziona ActivityPub / Mastodon.

shkspr.mobi/blog/2024/02/activ…

@Che succede nel Fediverso?


ActivityPub Server in a Single PHP File


shkspr.mobi/blog/2024/02/activ…

Any computer program can be designed to run from a single file if you architect it wrong enough!

I wanted to create the simplest possible Fediverse server which can be used as an educational tool to show how ActivityPub / Mastodon works.

The design goals were:

  • Upload a single PHP file to the server.
  • No databases or separate config files.
  • Single Actor (i.e. not multi-user).
  • Allow the Actor to be followed.
  • Post plain-text messages to followers.
  • Be roughly standards compliant.

And those goals have all been met! Check it out on GitLab. I warn you though, it is the nadir of bad coding. There are no tests, bugger-all security, scalability isn't considered, and it is a mess. But it works.

You can follow the test user @[url=https://example.viii.fi/example]example@example.viii.fi[/url]

Architecture


Firstly, I've slightly cheated on my "single file" stipulation. There's an .htaccess file which turns example.com/whatever into example.com/index.php?path=whatever

The index.php file then takes that path and does stuff. It also contains all the configuration variables which is very bad practice.

Rather than using a database, it saves files to disk.

Again, this is not suitable for any real world use. This is an educational tool to help explain the basics of posting messages to the Fediverse. It requires absolutely no dependencies. You do not need to spin up a dockerised hypervisor to manage your node bundles and re-compile everything to WASM. Just FTP the file up to prod and you're done.

Walkthrough


This is a quick ramble through the code. It is reasonably well documented, I hope.

Preamble


This is where you set up your account's name and bio. You also need to provide a public/private keypair. The posting page is protected with a password that also needs to be set here.
PHP // Set up the Actor's information $username = rawurlencode("example"); // Encoded as it is often used as part of a URl $realName = "E. Xample. Jr."; $summary = "Some text about the user."; $server = $_SERVER["SERVER_NAME"]; // Domain name this is hosted on // Generate locally or from cryptotools.net/rsagen // Newlines must be replaced with "\n" $key_private = "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"; $key_public = "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"; // Password for sending messages $password = "P4ssW0rd";

Logging


ActivityPub is a "chatty" protocol. This takes all the requests your server receives and saves them in /logs/ as a datestamped text file.
PHP // Get all headers and requests sent to this server $headers = print_r( getallheaders(), true ); $postData = print_r( $_POST, true ); $getData = print_r( $_GET, true ); $filesData = print_r( $_FILES, true ); $body = json_decode( file_get_contents( "php://input" ), true ); $bodyData = print_r( $body, true ); $requestData = print_r( $_REQUEST, true ); $serverData = print_r( $_SERVER, true ); // Get the type of request - used in the log filename if ( isset( $body["type"] ) ) { $type = " " . $body["type"]; } else { $type = ""; } // Create a timestamp in ISO 8601 format for the filename $timestamp = date( "c" ); // Filename for the log $filename = "{$timestamp}{$type}.txt"; // Save headers and request data to the timestamped file in the logs directory if( ! is_dir( "logs" ) ) { mkdir( "logs"); } file_put_contents( "logs/{$filename}", "Headers: \n$headers \n\n" . "Body Data: \n$bodyData \n\n" . "POST Data: \n$postData \n\n" . "GET Data: \n$getData \n\n" . "Files Data: \n$filesData \n\n" . "Request Data:\n$requestData\n\n" . "Server Data: \n$serverData \n\n" );

Routing


The .htaccess changes /whatever to /?path=whateverThis runs the function of the path requested.
PHP !empty( $_GET["path"] ) ? $path = $_GET["path"] : die(); switch ($path) { case ".well-known/webfinger": webfinger(); case rawurldecode( $username ): username(); case "following": following(); case "followers": followers(); case "inbox": inbox(); case "write": write(); case "send": send(); default: die(); }

WebFinger


The WebFinger Protocol is used to identify accounts.It is requested with example.com/.well-known/webfinger?resource=acct:username@example.comThis server only has one user, so it ignores the query string and always returns the same details.
PHP function webfinger() { global $username, $server; $webfinger = array( "subject" => "acct:{$username}@{$server}", "links" => array( array( "rel" => "self", "type" => "application/activity+json", "href" => "https://{$server}/{$username}" ) ) ); header( "Content-Type: application/json" ); echo json_encode( $webfinger ); die(); }

Username


Requesting example.com/username returns a JSON document with the user's information.
PHP function username() { global $username, $realName, $summary, $server, $key_public; $user = array( "@context" => [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1" ], "id" => "https://{$server}/{$username}", "type" => "Person", "following" => "https://{$server}/following", "followers" => "https://{$server}/followers", "inbox" => "https://{$server}/inbox", "preferredUsername" => rawurldecode($username), "name" => "{$realName}", "summary" => "{$summary}", "url" => "https://{$server}", "manuallyApprovesFollowers" => true, "discoverable" => true, "published" => "2024-02-12T11:51:00Z", "icon" => [ "type" => "Image", "mediaType" => "image/png", "url" => "https://{$server}/icon.png" ], "publicKey" => [ "id" => "https://{$server}/{$username}#main-key", "owner" => "https://{$server}/{$username}", "publicKeyPem" => $key_public ] ); header( "Content-Type: application/activity+json" ); echo json_encode( $user ); die(); }

Following & Followers


These JSON documents show how many users are following / followers-of this account.The information here is self-attested. So you can lie and use any number you want.
PHPfunction following() { global $server; $following = array( "@context" => "https://www.w3.org/ns/activitystreams", "id" => "https://{$server}/following", "type" => "Collection", "totalItems" => 0, "items" => [] ); header( "Content-Type: application/activity+json" ); echo json_encode( $following ); die(); } function followers() { global $server; $followers = array( "@context" => "https://www.w3.org/ns/activitystreams", "id" => "https://{$server}/followers", "type" => "Collection", "totalItems" => 0, "items" => [] ); header( "Content-Type: application/activity+json" ); echo json_encode( $followers ); die(); }

Inbox


The /inbox is the main server. It receives all requests. This server only responds to "Follow" requests.A remote server sends a follow request which is a JSON file saying who they are.This code does not cryptographically validate the headers of the received message.The name of the remote user's server is saved to a file so that future messages can be delivered to it.An accept request is cryptographically signed and POST'd back to the remote server.
PHP function inbox() { global $body, $server, $username, $key_private; // Get the message and type $inbox_message = $body; $inbox_type = $inbox_message["type"]; // This inbox only responds to follow requests if ( "Follow" != $inbox_type ) { die(); } // Get the parameters $inbox_id = $inbox_message["id"]; $inbox_actor = $inbox_message["actor"]; $inbox_host = parse_url( $inbox_actor, PHP_URL_HOST ); // Does this account have any followers? if( file_exists( "followers.json" ) ) { $followers_file = file_get_contents( "followers.json" ); $followers_json = json_decode( $followers_file, true ); } else { $followers_json = array(); } // Add user to list. Don't care about duplicate users, server is what's important $followers_json[$inbox_host]["users"][] = $inbox_actor; // Save the new followers file file_put_contents( "followers.json", print_r( json_encode( $followers_json ), true ) ); // Response Message ID // This isn't used for anything important so could just be a random number $guid = uuid(); // Create the Accept message $message = [ "@context" => "https://www.w3.org/ns/activitystreams", "id" => "https://{$server}/{$guid}", "type" => "Accept", "actor" => "https://{$server}/{$username}", "object" => [ "@context" => "https://www.w3.org/ns/activitystreams", "id" => $inbox_id, "type" => $inbox_type, "actor" => $inbox_actor, "object" => "https://{$server}/{$username}", ] ]; // The Accept is sent to the server of the user who requested the follow // TODO: The path doesn't *always* end with/inbox $host = $inbox_host; $path = parse_url( $inbox_actor, PHP_URL_PATH ) . "/inbox"; // Get the signed headers $headers = generate_signed_headers( $message, $host, $path ); // Specify the URL of the remote server's inbox // TODO: The path doesn't *always* end with /inbox $remoteServerUrl = $inbox_actor . "/inbox"; // POST the message and header to the requester's inbox $ch = curl_init( $remoteServerUrl ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" ); curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($message) ); curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers ); $response = curl_exec( $ch ); // Check for errors if( curl_errno( $ch ) ) { file_put_contents( "error.txt", curl_error( $ch ) ); } curl_close($ch); die(); }

UUID


Every message sent should have a unique ID. This can be anything you like. Some servers use a random number.I prefer a date-sortable string.
PHP function uuid() { return sprintf( "%08x-%04x-%04x-%04x-%012x", time(), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffffffffffff) ); }

Signing Headers


Every message that your server sends needs to be cryptographically signed with your Private Key.This is a complicated process. Please read "How to make friends and verify requests" for more information.
PHP function generate_signed_headers( $message, $host, $path ) { global $server, $username, $key_private; // Encode the message to JSON $message_json = json_encode( $message ); // Location of the Public Key $keyId = "https://{$server}/{$username}#main-key"; // Generate signing variables $hash = hash( "sha256", $message_json, true ); $digest = base64_encode( $hash ); $date = date( "D, d M Y H:i:s \G\M\T" ); // Get the Private Key $signer = openssl_get_privatekey( $key_private ); // Sign the path, host, date, and digest $stringToSign = "(request-target): post $path\nhost: $host\ndate: $date\ndigest: SHA-256=$digest"; // The signing function returns the variable $signature // php.net/manual/en/function.ope… openssl_sign( $stringToSign, $signature, $signer, OPENSSL_ALGO_SHA256 ); // Encode the signature $signature_b64 = base64_encode( $signature ); // Full signature header $signature_header = 'keyId="' . $keyId . '",algorithm="rsa-sha256",headers="(request-target) host date digest",signature="' . $signature_b64 . '"'; // Header for POST reply $headers = array( "Host: {$host}", "Date: {$date}", "Digest: SHA-256={$digest}", "Signature: {$signature_header}", "Content-Type: application/activity+json", "Accept: application/activity+json", ); return $headers; }

User Interface for Writing


This creates a basic HTML form. Type in your message and your password. It then POSTs the data to the /send endpoint.
PHP function write() { // Display an HTML form for the user to enter a message.echo <<< HTML<![url=https://mastodon.social/users/doctype]Aleks Dorohovich[/url] html><html lang="en-GB"> <head> <meta charset="UTF-8"> <title>Send Message</title> <style> *{font-family:sans-serif;font-size:1.1em;} </style> </head> <body> <form action="/send" method="post" enctype="multipart/form-data"> <label for="content">Your message:</label><br> <textarea id="content" name="content" rows="5" cols="32"></textarea><br> <label for="password">Password</label><br> <input type="password" name="password" id="password" size="32"><br> <input type="submit" value="Post Message"> </form> </body></html>HTML; die(); }

Send Endpoint


This takes the submitted message and checks the password is correct.It reads the followers.json file and sends the message to every server that is following this account.
PHP function send() { global $password, $server, $username, $key_private; // Does the posted password match the stored password? if( $password != $_POST["password"] ) { die(); } // Get the posted content $content = $_POST["content"]; // Current time - ISO8601 $timestamp = date( "c" ); // Outgoing Message ID $guid = uuid(); // Construct the Note // contentMap is used to prevent unnecessary "translate this post" pop ups // hardcoded to English $note = [ "@context" => array( "https://www.w3.org/ns/activitystreams" ), "id" => "https://{$server}/posts/{$guid}.json", "type" => "Note", "published" => $timestamp, "attributedTo" => "https://{$server}/{$username}", "content" => $content, "contentMap" => ["en" => $content], "to" => ["https://www.w3.org/ns/activitystreams#Public"] ]; // Construct the Message $message = [ "@context" => "https://www.w3.org/ns/activitystreams", "id" => "https://{$server}/posts/{$guid}.json", "type" => "Create", "actor" => "https://{$server}/{$username}", "to" => [ "https://www.w3.org/ns/activitystreams#Public" ], "cc" => [ "https://{$server}/followers" ], "object" => $note ]; // Create the context for the permalink $note = [ "@context" => "https://www.w3.org/ns/activitystreams", ...$note ]; // Save the permalink $note_json = json_encode( $note ); // Check for posts/ directory and create it if( ! is_dir( "posts" ) ) { mkdir( "posts"); } file_put_contents( "posts/{$guid}.json", print_r( $note_json, true ) ); // Read existing users and get their hosts $followers_file = file_get_contents( "followers.json" ); $followers_json = json_decode( $followers_file, true ); $hosts = array_keys( $followers_json ); // Prepare to use the multiple cURL handle $mh = curl_multi_init(); // Loop through all the severs of the followers // Each server needs its own cURL handle // Each POST to an inbox needs to be signed separately foreach ( $hosts as $host ) { $path = "/inbox"; // Get the signed headers $headers = generate_signed_headers( $message, $host, $path ); // Specify the URL of the remote server $remoteServerUrl = "https://{$host}{$path}"; // POST the message and header to the requester's inbox $ch = curl_init( $remoteServerUrl ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" ); curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($message) ); curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers ); // Add the handle to the multi-handle curl_multi_add_handle( $mh, $ch ); } // Execute the multi-handle do { $status = curl_multi_exec( $mh, $active ); if ( $active ) { curl_multi_select( $mh ); } } while ( $active && $status == CURLM_OK ); // Close the multi-handle curl_multi_close( $mh ); // Render the JSON so the user can see the POST has worked header( "Location: https://{$server}/posts/{$guid}.json" ); die(); }

Next Steps


This is not intended to be used in production. Ever. But if you would like to contribute more simple examples of how the protocol works, please come and play on GitLab.

You can follow the test user @[url=https://example.viii.fi/example]example@example.viii.fi[/url]

#activitypub #mastodon #php


reshared this



Building a Simple Ribbon Synth


The usual input device for playing a synthesizer is the good old piano keyboard. However, you don’t have to stick to such pedestrian interfaces when making music. [Daisy] has a fun build that shows us how to put together a ribbon synth that makes wonderful little noises.

Naturally, the heart of the build is a ribbon potentiometer (also known as soft pots). It’s essentially a touch sensitive strip that changes in resistance depending on where you touch it. You can slide your finger up and down to vary the output continuously; in musical contexts, they can behave rather like a fretless instrument. [Daisy] employs one of these potentiometers in such a role by hooking it up to a Daisy Seed microcontroller board, which reads it with an analog-to-digital converter (ADC). The resistance values are used to vary the pitch of a dual-saw synthesizer programmed in the plugdata framework.

We’ve featured some other great ribbon synths over the years, too, like this tribute to the Eowave Persephone. They’re not the ideal choice for those that prefer their notes on pitch, but they’re beautifully fun to play with when you’re getting a little more experimental.

youtube.com/embed/iUDOLJ1Ki84?…


hackaday.com/2025/11/29/buildi…



Assalto a La Stampa. La solidarietà di Stampa Romana


L’Associazione Stampa Romana esprime solidarietà ai giornalisti de La Stampa per l’assalto alla redazione avvenuto ieri a Torino. Un episodio gravissimo, per di più messo in atto durante lo sciopero dei giornalisti per il rinnovo del contratto nazionale di lavoro, che è un attacco a tutta l’informazione, presidio di libertà e cardine della dialettica democratica.

La Segreteria dell’ASR


dicorinto.it/associazionismo/a…



Il 10 dicembre evento di Articolo 21 nella sede di Libera. Riflessione sulla “strategia della tensione” con la rappresentazione di “Io so”


Quest’anno la festa annuale di Articolo 21 si terrà il 10 dicembre e sarà incentrata nell’approfondimento della strategia della tensione. Una data non casuale, per ricordare la strage di Piazza Fontana, l’attentato terroristico avvenuto il 12 dicembre 1969 nella sede della Banca Nazionale dell’Agricoltura a Milano, che causò la morte di 17 persone. L’appuntamento è alle 17 in via Stamira 5 a Roma, sede di Libera che aderisce al programma. Momento clou dell’evento sarà la rappresentazione teatrale “Io so” a cura di Associazione TerraTerra, di e con Elena Ruzza, testo di Davide Rigallo e musiche di Matteo Cantamessa.

Introducono la portavoce e il presidente di Articolo 21, Elisa Marincola e Paolo Borrometi, con Giampiero Cioffredi, responsabile di Libera Lazio e Gian Mario Gillio, giornalista di Riforma-Eco delle valli valdesi

Dopo lo spettacolo Elisa Signori Rocchelli interverrà sul tema “Quel filo che lega il passato al presente”; a seguire Beppe Giulietti intervista Manlio Milani, coordinatore delle associazioni dei familiari vittime delle stragi. Manlio Milani riceverà il Premio Articolo 21 per il 2025.

Vi aspettiamo.

Il 10 dicembre evento di Articolo 21 nella sede di Libera. Riflessione sulla “strategia della tensione” con la rappresentazione di “Io so”


articolo21.org/2025/11/io-so-r…


dicorinto.it/associazionismo/i…



Il Papa in raccoglimento silenzioso, nella sua “prima volta” da Pontefice nella Moschea Blu. E’ cominciato così il terzo giorno del viaggio di Leone XIV ad Istanbul, dove è risuonata in modo particolare la parola “unità”, come dono e come compito, se…


"In Turchia, come a Nicea 17 secoli fa, la Chiesa sta ritrovando l’unità e la professione dell’unica fede, e lungo il cammino verso la piena comunione tra i cristiani progredisce sotto la guida saggia del nostro amato patriarca Bartolomeo".


Hacky Thanksgiving


It’s that time of year when we eat perhaps a little too much food, and have maybe just a few too many sips of red wine. But it’s also when we think about what we’ve been grateful for over the past year. And here at Hackaday, that’s you all: the people out there making the crazy projects that we get the pleasure of writing about, and those of you just reading along. After all, we’re just the hackers in the middle. You are all Hackaday.

And it’s also the time of year, at least in this hemisphere, when the days get far too short for their own good and the weather gets frankly less than pleasant. That means more time indoors, and if we play our cards right, more time in the lab. Supercon is over and Hackaday Europe is still far enough in the future. Time for a good project along with all of the festive duties.

So here we sit, while the weather outside is frightful, wishing you all a pleasant start to the holiday season. May your parts bin overflow and your projects-to-do-list never empty!

This article is part of the Hackaday.com newsletter, delivered every seven days for each of the last 200+ weeks. It also includes our favorite articles from the last seven days that you can see on the web version of the newsletter. Want this type of article to hit your inbox every Friday morning? You should sign up!


hackaday.com/2025/11/29/hacky-…



Presto la pubblicità su ChatGPT! Sarà ultra mirata e fine delle testate online


Finora ChatGPT è stato privo di pubblicità: niente banner, niente promozioni nascoste. Anche le versioni a pagamento funzionavano senza offerte insistenti. Ma le cose potrebbero cambiare presto.

Come segnalato dall’utente X (ex Twitter ) con lo pseudonimo Tibor , nella versione beta dell’app Android ChatGPT (1.2025.329) sono comparsi riferimenti a una nuova funzionalità pubblicitaria. Il codice conteneva frasi come “funzione pubblicitaria”, “contenuto bazaar”, nonché “annuncio di ricerca” e “carousel di annunci di ricerca”.

Per ora, sembra che gli annunci pubblicitari appariranno solo nelle ricerche integrate, ad esempio quando l’intelligenza artificiale accede a Internet per rispondere a una query. Ma col tempo, le possibilità potrebbero espandersi ulteriormente.

Ciò che è particolarmente interessante è che la pubblicità potenziale in ChatGPT può essere altamente personalizzata. L’intelligenza artificiale conosce molti dettagli dell’utente, a meno che, ovviamente, le impostazioni pertinenti non siano disattivate.

Ciò significa che il targeting sarà personalizzato non semplicemente in base agli interessi generali, come sui social media, ma specificamente in base al comportamento e alle esigenze di una persona specifica.

OpenAI non ha ancora annunciato ufficialmente il lancio della pubblicità, né ha specificato quando o come potrebbe apparire.

Ma il fatto stesso che tali elementi siano già presenti nel codice indica che il vettore di monetizzazione sta cambiando. Se ChatGPT iniziasse a guadagnare dalla pubblicità, ciò potrebbe avere un impatto non solo sul prodotto stesso, ma anche sul modo in cui interagiremo con i chatbot in futuro e su quanto potremo fidarci di loro (questa rimane una questione aperta).

L'articolo Presto la pubblicità su ChatGPT! Sarà ultra mirata e fine delle testate online proviene da Red Hot Cyber.



“Viviamo in un mondo in cui troppo spesso la religione è usata per giustificare guerre e atrocità”. Lo ha denunciato il Papa, che nell’omelia della messa presieduta nella Volkswagen Arena si è rivolto anche agli appartenenti alle comunità non cristia…


ma sono rincoglionita o i profili esistono da una vita? sul pc di mia madre ho da anni firefox con il profilo di mia madre e il mio... con icone di lancio distinte naturalmente. e tutto diverso dentro.


“La stessa fede nel Salvatore ci unisce non solo tra noi, ma con tutti i fratelli e le sorelle appartenenti ad altre Chiese e Comunità cristiane. Lo abbiamo sperimentato ieri, nella preghiera a İznik”.


“Favorire e rafforzare i legami che ci uniscono, per arricchirci reciprocamente ed essere davanti al mondo segno credibile dell’amore universale e infinito del Signore”.


“Quanto bisogno di pace, di unità e di riconciliazione c’è attorno a noi, e anche in noi e tra noi!”. Lo ha esclamato il Papa, nell’omelia della messa pronunciata in inglese e presieduta nella Volkswagen Arena.


“Rinnovare nella fede la forza della nostra testimonianza”. È il primo invito del Papa, nell’omelia della messa presieduta alla Volkswagen Arena, ultimo impegno pubblico della sua terza giornata in Turchia.



“Memori del 60° anniversario della dichiarazione Nostra Aetate, esortiamo tutti gli uomini e le donne di buona volontà a lavorare insieme per costruire un mondo più giusto e solidale e a prendersi cura del creato, che Dio ci ha affidato”.


“L'obiettivo dell'unità dei cristiani include il fine di contribuire in modo fondamentale e vivificante alla pace tra tutti i popoli. Insieme alziamo fervidamente le nostre voci invocando il dono divino della pace sul nostro mondo”.


“Presentare al mondo una rinnovata testimonianza di pace, riconciliazione e unità”. È il compito affidato alla Chiesa cattolica e a quella ortodossa – e in particolare a “quanti sono ancora titubanti verso qualsiasi forma di dialogo” – nella dichiara…


Scientists found that major celebrities died four years earlier than their less famous peers, hinting that fame itself can be a mortality risk.#TheAbstract


Being Famous Can Shorten Your Lifespan, Scientists Find


Welcome back to the Abstract! Here are the studies this week that hit the books, bottled alien lightning, reared wolf cubs, and tallied the price of fame.

First, we’ve got a centuries-long history of an Indian savannah told through songs, folktales, and screaming peacocks. Then: Mars gets charged, the secrets of Stora Karlsö, and the epidemiology of stardom.

As always, for more of my work, check out my book First Contact: The Story of Our Obsession with Aliens or subscribe to my personal newsletter the BeX Files.

When folk tales are field guides


Nerlekar, Ashish N. et al. “Utilizing traditional literature to triangulate the ecological history of a tropical savanna.” People and Nature.

It has happened again: Researchers have turned to the annals of literature to address a scientific question. Longtime readers of the Abstract will recall that this is a simply irresistible category of research to me (see: China’s porpoise corpus, Transylvanian weather reports, and milky seas). To the library!

In this edition of Science from the Stacks, researchers probed the origins of the tropical savannah in western Maharashtra, India, by collecting references to plants in 28 stories and songs dating back at least 750 years. The aim was to reconstruct a vegetation history that could hint at shifts in the region between forest and savannah biomes.

“Ttraditional literature—for example, myths, folk songs and stories—is a culturally resonant, yet underutilized line of evidence to understand ecological histories and foster biodiversity conservation,” said researchers led by Ashish N. Nerlekar of Michigan State University.
A folio from an early 19th-century manuscript of the Bhaktavijaya mentioning the taraṭī tree. Image: Nerlekar, Ashish N. et al.
“We found that descriptions of both the landscape and specific plants point to an open-canopy savanna in the past rather than a forest,” the team said. “Of the 44 wild plant species recorded (i.e. omitting exclusively cultivated plants), a clear majority (27 species) were savanna indicators, 14 were generalists, and only three were forest indicators. Our ecological reconstructions from traditional literature complement data from archival paintings, revenue records, plant and animal fossils, and dated molecular phylogenies of endemic biodiversity—all attesting to the antiquity of India's savannas.”

It’s an out-of-the-box way to reconstruct the natural history of a region. But the highlights of these studies are always the excerpts from the literature, like the amazing origin story of this village:

“A folk tale illustrates the founding myth of Kolvihire village near Jejuri. The tale is about a robber-murderer named Vālhyā Koḷī, who lived near Kolvihire. Upon meeting a sage, Vālhyā Koḷī introspected on his wrongdoings and performed penance for 12 years. After completion of the penance, as a living testimony to Vālhyā Koḷī's sincere devotion, leaves sprouted from his stick, which he had used to hit and kill travellers to loot their money. Eventually, Vālhyā Koḷī became the sage-poet Vālmikī. According to the tale, the sprouted stick grew into a pāḍaḷa tree, and the tree still exists in Kolvihire.”

You have to love a good botanical redemption story. Another standout line is this memorable description of a thorny patch in the savannah from the early 16th century: “Such is this thorny forest | it is highly frightening | this forest is empty | peacocks scream here.”

I don’t know exactly why, but “peacocks scream here” is just about the scariest description I’ve ever heard of a place. Shout out to this ancient poet for capturing some legendary bad vibes.

In other news…

Extraterrestrial electricity


Chide, Baptiste et al. “Detection of triboelectric discharges during dust events on Mars.” Nature.

Lightning is a big deal on Earth, inspiring awe, fear, and some of the naughtiest deities imaginable. But lightning also strikes on other planets, including Jupiter and Saturn. For years, scientists have suspected that Mars might host its own bolts, but detecting them has remained elusive.

Now, scientists have finally captured lightning on Mars thanks to “serendipitous observations” from the SuperCam microphone aboard the Perseverance rover.

“Fifty-five events have been detected over two Martian years, usually associated with dust devils and dust storm convective fronts,” said researchers led by Baptiste Chide of the Institut de Recherche en Astrophysique et Planétologie in Toulouse, France. “Beyond Mars, this work also reinforces the prospect of triboelectric discharges associated with wind-blown sediment on Venus and Titan.”

It goes to show that even a very dead world like Mars can still crackle and zap now and then.

The wolves of Stora Karlsö


Girdland-Flink, Linus et al. “Gray wolves in an anthropogenic context on a small island in prehistoric Scandinavia.” Proceedings of the National Academy of Sciences.”

About 4,000 years ago on a small island in the Baltic sea, people cared for two wolves — perhaps as pets — feeding them fish, seals, and other marine fare. That’s the cozy portrait presented in a new study that analyzed the remains of ancient wolves buried in the Stora Förvar cave on the Swedish island of Stora Karlsö.

While dogs are commonly buried at ancient human sites, wolves and humans rarely mix in the archaeological record. But the wolves at Stora Karlsö were unlikely to have reached the island without the aid of humans, and their primarily seafood diet—unusual for wild wolves—suggests they were also fed by people. Moreover, one of the animals suffered from a pathology that might have limited its mobility, hinting that it was kept alive by humans.

The cave where the wolf remains were found. Image: Jan Storå/Stockholm University

The study presents the “possibility of prehistoric human control of wolves,” said researchers led by Linus Girdland-Flink of the University of Aberdeen. “Our results provide evidence that extends the discourse about past human–wolf interactions and relationships.”

Fame! I’m going to live forever (or not)


Hepp, Johanna et al. “The price of fame? Mortality risk among famous singers.” Journal of Epidemiology and Community Health.

Celebrity may literally be to die for, according to a new study that evaluated fame as a comorbidity.

Scientists collected a list of 324 big music stars active between 1950 and 1990, including Elvis Presley, Kurt Cobain, Sam Cooke, and Janis Joplin. Those heavy-hitters were then matched with 324 “twin” musicians that were not household names, but otherwise shared many characteristics of the celebs, including gender, nationality, genre, and roughly similar birth dates. The idea was to directly compare the lifespans of A-listers and B-listers to isolate the extent to which fame itself is a mortality risk factor, rather than the lifestyle of a musician.

The study suggests that famous singers die four years earlier, on average, compared to their B-list peers, demonstrating “a 33% higher mortality risk compared with less famous singers,” said researchers led by Johanna Hepp of the Central Institute of Mental Health in Mannheim, Germany. “This study provides new evidence suggesting that fame may be associated with increased mortality risk among musicians, beyond occupational factors.”

Lady Gaga had it right, as if there were ever any doubt: Under the glitz, the Fame Monster is always waiting.

Thanks for reading! See you next week.





“Oltre a riconoscere gli ostacoli che impediscono il ripristino della piena comunione tra tutti i cristiani – ostacoli che cerchiamo di affrontare attraverso la via del dialogo teologico – dobbiamo anche riconoscere che ciò che ci unisce è la fede es…



Dopo la doxologia nella chiesa patriarcale di San Giorgio a Istanbul, Papa Leone XIV e il patriarca Bartolomeo hanno firmato una dichiarazione congiunta, nella sede del Patriarcato ecumenico, dove c'è stato un incontro con le delegazioni e un breve i…


“Una voce unica nella Chiesa unificata”. Così il patriarca ecumenico e arcivescovo di Costantinopoli, Bartolomeo, ha definito lo storico pellegrinaggio di ieri a Iznik, l’antica Nicea.


Sarà dedicata al tema “Lievito di pace e di speranza. Cammini e prospettive della Chiesa diocesana” l’assemblea pastorale che si terrà nel pomeriggio di domani, domenica 30 novembre, Centro pastorale diocesano di Fano.





How To Print PETG as Transparently as Possible


PETG filament can be had in a variety of colors, just like any other. You can even get translucent or transparent forms if you want to print something vaguely see-through. But if you’re looking for a bit more visually impressive, you might like to pick up a few tips from [Tej Grewal] on making sure your prints come out as clear as possible.
Standard print settings aren’t great for transparency.
It all comes down to pathing of the 3D printer’s hot end. If it’s zigzagging back and forth, laying down hot plastic in all different orientations from layer to layer, you’re going to get a hazy, ugly, result that probably doesn’t look very see-through at all.

However, you can work around this by choosing slicer settings that make the tool pathing more suitable for producing a clearer part. [Tej] recommends going slow — as little as 20 mm/s during printing. He also states that removing top and bottom shells and setting wall loops to 1 can help to produce a part that’s entirely infill. Then, you’ll want to set infill to 100% and the direction to 0 or 90 degrees. This will ensure your hot end is just making long, straight strokes for layer after layer that will best allow light to pass through. You’ll also want to maximize nozzle flow to avoid any unsightly gaps or bubbles in your print.

[Tej] demonstrates the technique by creating a cover for a display. By using the settings in question, he creates a far more transparent plate, compared to the original part that has an ugly zig-zagging haze effect. You’re not going to get something optically clear this way; the final results are more lightly frosted, but still good.

Transparency will never be something 3D printers are great at. However, we have seen some interesting post-processing techniques that will blow your mind in this regard.


hackaday.com/2025/11/29/how-to…



Ottavia Piccolo: “Matteotti è più attuale che mai”


@Giornalismo e disordine informativo
articolo21.org/2025/11/ottavia…
Giacomo Matteotti ci parla ancora. Per il suo coraggio, per la sua umanità, per la sua passione politica e civile, per l’entusiasmo col quale si lanciava in ogni sfida, per la forza d’animo con la quale sfidò il fascismo fino a



Il Papa ha nominato il card. Pietro Parolin, Segretario di Stato vaticano, legato pontificio per la celebrazione eucaristica che si terrà domenica 11 gennaio 2026, in occasione dell’VIII centenario della cattedrale di Bruxelles.


UCRAINA. Corruzione, nuova tegola su Zelensky


@Notizie dall'Italia e dal mondo
Il presidente ucraino è costretto a licenziare il suo capo di gabinetto e capo negoziatore Andrii Yermak, accusato di essere a capo di una vasta rete di corruzione
L'articolo UCRAINA. Corruzione, nuova tegola su Zelensky proviene da pagineesteri.it/2025/11/29/eur…



hwupgrade.it/news/sistemi-oper…

da utente Linux è divertente vedere microsoft e i suoi utenti ostinarsi a usare qualcosa che fatica così tanto a funzionare. chi è causa del suo mal pianga se stesso.



“On the historic occasion in which we celebrate 1700 years since the Ecumenical Council of Nicea, we gather to renew our faith in Jesus Christ true God and true man, celebrating the faith we share together.


Kirk Knuffke, Stomu Takeishi, Bill Goodwin – Window
freezonemagazine.com/articoli/…
Window è il nuovo album in studio dell’acclamato cornettista Kirk Knuffke, che presenta sia il suo approccio distintivo come strumentista sia, in tre brani, un aspetto vocale raramente ascoltato della sua arte. Accompagnato dal bassista Stomu Takeishi e dal leggendario batterista jazz Bill Goodwin, un signore che si porta 83 primavere sulle spalle con