Docela mě překvapuje, že tado zkrácená adresa na tehdy populárním bit.ly ještě po čtrnácti letech funguje a vede na wiki stránku Pakistan Air Force.
vitsoft
pátek 7. července 2023
Můj milý deníčku 2008-9
Docela mě překvapuje, že tado zkrácená adresa na tehdy populárním bit.ly ještě po čtrnácti letech funguje a vede na wiki stránku Pakistan Air Force.
pátek 6. ledna 2023
Tweety a tooty jako plaintext
Twitter umožňuje stažení dat, které o nás nashromáždil, stačí požádat na twitter.com/settings/account a počkat si 24 hodin. Po rozbalení stažené zálohy ji můžeme zkoumat internetovým prohlížečem v souboru "Your archive.html". To mi ale moc nevyhovovalo, protože archiv tweetů je rozdělen na sloupce Tweets, Replies, Retweets a hlavně proto, že je při scrolování dotahuje dynamicky javascriptem, takže v prohlížeči pořádně nefunguje vyhledávání pomocí Ctrl-F. Tim Hutton napsal script parser.py, který vylepšuje několik nedostatků, ale problém prohledávání všech twítů najednou neřeší.
Vyrobil jsem si tedy script, který převádí twíty z formátu objektů JSON v souboru "data/tweets.js" na prostý text, nahradí zkrácené internetové adresy uváděné v textu za jejich plné, funkční verze a chronologicky seřadí vlastní twíty včetně těch odpovědních. Nelze bohužel zobrazovat celé konverzace, protože cizí twíty v archivu nejsou. Textová podoba archivu může vypadat nějak takto:
--- 2015-06-29 (Mon) 17:51 [4419] https://twitter.com/vitsoft/status/615548191421939712 Manželka neječí. Je prý to její normální hlas a mne zmátlo, že první měsíce po svatbě jen šeptala. #genderboj --- 2015-06-30 (Tue) 10:56 [4420] https://twitter.com/vitsoft/status/615806000742797313 RT @selner84: Tsipras: "Zdravíme Českou republiku." https://pbs.twimg.com/media/CIu4mRiUsAARtdf.jpg --- 2015-06-30 (Tue) 16:07 [4421] https://twitter.com/vitsoft/status/615884292237971457 Ale chlapci, vždyť my už ten Peroutkův článek hledáme sedmý rok! A to už, nezlobte se, to už přestává být vtipné. #Cimrman --- 2015-07-01 (Wed) 08:59 [4422] https://twitter.com/vitsoft/status/616139003679612928 in reply to https://twitter.com/mppoky/status/615983067157647360 @mppoky Výhodou vhodně zvolených nicků je, že pokud jim chceme něco sdělit, netřeba to psát, stačí mention. @lehni_kua
Chcete-li můj script použít, je potřeba mít na počítači instalován PHP a následující kód uložit pomocí schránky do souboru nazvaného např.
"tweet2text.php".
Před spuštěním v příkazovém okně pomocí "\cesta\k\php.exe" tweet2text.php je třeba upravit parametry v jeho záhlaví, především adresář, ve kterém je rozbalen vstupní soubor, a název výstupního textového souboru. Syntaxe PHP vyžaduje, aby zpětná lomítka \ byla v cestě k souborům zdvojena.
Parametr $OutEncoding="UTF-16//IGNORE" je vhodný k prohlížení výstupního textu Notepadem nebo PSPadem, aby se správně zobrazovala asijská písma a emoji. Lze ovšem nastavit i osmibitové ANSI kodování "CP1250". Přidání //IGNORE přikazuje ignorovat (vynechávat) chybně zakódované znaky z textu twítu. Na Linuxu by mělo fungovat $OutEncoding="UTF-8".
<?php /* Script for conversion of your tweets from input file "tweets.js" to a plain-text output file. Download and unzip the archive of your data from https://twitter.com/settings/account Edit the following parameters in this script and execute it with PHP interpreter. */ $System="https://twitter.com/"; // URL of the server. $Account="vitsoft"; // Screen_name of the account owner. $InpFile="D:\\DAT\\BACKUP\\twitter\\data\\tweets.js"; // JSON-formated archive of tweets in UTF-8 encoding. $OutFile="D:\\DAT\\BACKUP\\twitter\\tweets.txt"; // Plain-text output file in $OutEncoding. $OutEncoding="UTF-16//IGNORE"; // Encoding wanted in $OutFile (UTF-16 for MS Notepad). $DateFormat="Y-m-d (D) H:i"; if (!file_exists($InpFile)) die(PHP_EOL."Input file \"$InpFile\" was not found."); if (!$OutHandle=fopen($OutFile,"w")) die(PHP_EOL."Cannot write to the output file \"$OutFile\"."); echo PHP_EOL."Parsing input file \"$InpFile\" ..."; $FileHeader="window.YTD.tweets.part0 = "; // This header needs to be removed from "tweets.js". $InpArray=json_decode(substr(file_get_contents($InpFile),strlen($FileHeader)),true); if (json_last_error()!=JSON_ERROR_NONE) die(PHP_EOL."Last JSON-error in \"tweets.js\": ".json_last_error_msg()); if (!$OutHandle=fopen($OutFile,"w")) die(PHP_EOL."Cannot write to the output file \"$OutFile\"."); fwrite($OutHandle,iconv("UTF-8",$OutEncoding, "--- Plain-text tweets converted from \"$InpFile\" ".date($DateFormat).PHP_EOL)); $OutArray=array(); // Convert relevant data from $InpArray to $OutArray. foreach ($InpArray as $TtNr => $Tweet) {$OutArray[$TtNr]['Date']=date($DateFormat,strtotime($Tweet['tweet']['created_at'])); $OutArray[$TtNr]['TtId']=$Tweet['tweet']['id_str']; if (array_key_exists('in_reply_to_status_id_str',$Tweet['tweet'])) // If $Tweet is a reply to another tweet. {$OutArray[$TtNr]['ReplyToTtId']=$Tweet['tweet']['in_reply_to_status_id_str']; if (array_key_exists('in_reply_to_screen_name',$Tweet['tweet'])) $OutArray[$TtNr]['ReplyToName']=$Tweet['tweet']['in_reply_to_screen_name']; else $OutArray[$TtNr]['ReplyToName']=$Account; // In case of reply to deleted tweet, renamed account etc. } $TweetText=$Tweet['tweet']['full_text']; // Replace displayed URL in $TweetText with the real expanded URL. if (array_key_exists('urls',$Tweet['tweet']['entities'])) foreach ($Tweet['tweet']['entities']['urls'] as $UA) $TweetText=str_replace($UA['url'],$UA['expanded_url'],$TweetText); if (array_key_exists('media',$Tweet['tweet']['entities'])) foreach ($Tweet['tweet']['entities']['media'] as $MA) $TweetText=str_replace($MA['url'],$MA['media_url_https'],$TweetText); $OutArray[$TtNr]['Txt']=$TweetText; } // Important information from $InpArray has been moved to $OutArray. function ByDate($a,$b) // Callback function for chronological sort of $OutArray. {if ($a['Date'] == $b['Date']) return 0; return ($a['Date'] < $b['Date'])?-1:1;} echo PHP_EOL."Sorting tweets by date ..."; usort($OutArray,"ByDate"); echo PHP_EOL."Writing output file \"$OutFile\" ..."; foreach ($OutArray as $TtNr => $Tweet) // Convertion of $OutArray to a plain text. {$PlainTweet=PHP_EOL."--- ".$Tweet['Date']." [".$TtNr."] $System$Account/status/".$Tweet['TtId']; if (array_key_exists('ReplyToTtId',$Tweet)) $PlainTweet.=PHP_EOL." in reply to $System".$Tweet['ReplyToName']."/status/".$Tweet['ReplyToTtId']; $PlainTweet.=PHP_EOL.$Tweet['Txt'].PHP_EOL; fwrite($OutHandle,iconv("UTF-8",$OutEncoding,$PlainTweet)); } fclose($OutHandle); echo PHP_EOL."Twitter archive was converted to the output file in $OutEncoding encoding."; ?>
Podobný skript bude fungovat i na mastodonový archiv tootů, o který lze požádat na adrese
https://your-mastodon-system/settings/export a po rozbalení jej opět v JSON podobě nalezneme v souboru "outbox.json". Místo your-mastodon-system je samozřejmě třeba dosadit doménu serveru s naším účtem, např. mastodonczech.cz, cztwitter.cz apod.
<?php /* Script for conversion of your toots from input file "outbox.json" to a plain-text output file. Download and unzip the archive of your Mastodon data from your-mastodon-system/settings/export. Edit the following parameters in this script and execute it with PHP interpreter. */ $System="https://mastodonczech.cz/system/"; // URL of path to the attached media files. $InpFile="D:\\DAT\\BACKUP\\mastodonczech\\outbox.json"; // JSON-formated archive of toots in UTF-8 encoding. $OutFile="D:\\DAT\\BACKUP\\mastodonczech\\mastodonarchive.txt"; // Plain-text output file in $OutEncoding. $OutEncoding="UTF-16//IGNORE"; // Encoding wanted in $OutFile (UTF-16 for MS Notepad). $DateFormat="Y-m-d (D) H:i"; if (!file_exists($InpFile)) die(PHP_EOL."Input file \"$InpFile\" was not found."); echo PHP_EOL."Parsing input file \"$InpFile\" ..."; $InpArray=json_decode(file_get_contents($InpFile),true); if (json_last_error()<>JSON_ERROR_NONE) die(PHP_EOL."Last JSON-error in \"$InpFile\": ".json_last_error_msg()); if (!$OutHandle=fopen($OutFile,"w")) die(PHP_EOL."Cannot write to the output file \"$OutFile\"."); fwrite($OutHandle,iconv("UTF-8",$OutEncoding, "--- Plain-text Mastodon toots converted from \"$InpFile\" ".date($DateFormat).PHP_EOL)); $OutArray=array(); // Convert relevant data from $InpArray to $OutArray. foreach ($InpArray['orderedItems'] as $TtNr => $Toot) {$Id=$Published=$InReplyTo=$Boosted=$Content="";$Attachments=array(); if (is_array($Toot['object'])) {$Id=$Toot['object']['id']; $Content=$Toot['object']['content']; $Published=$Toot['object']['published']; $InReplyTo=$Toot['object']['inReplyTo']; if (@is_array($Toot['object']['attachment'])) $Attachments=$Toot['object']['attachment']; } else { $Id=$Toot['id'];$Boosted=$Toot['object'];$Published=$Toot['published'];} $OutArray[$TtNr]['Date']=date($DateFormat,strtotime($Published)); $OutArray[$TtNr]['Id']=$Id; if ($InReplyTo) $OutArray[$TtNr]['InReplyTo']=$InReplyTo; if ($Boosted) $OutArray[$TtNr]['Boosted']=$Boosted; if (count($Attachments)) $OutArray[$TtNr]['Attachments']=$Attachments; $OutArray[$TtNr]['Txt']=str_replace(array('<p>','</p>','<br />'),array('',PHP_EOL,PHP_EOL),strip_tags($Content,'<p><br>')); } // Important information from $InpArray has been moved to $OutArray. function ByDate($a,$b) // Callback function for chronological sort of $OutArray. {if ($a['Date'] == $b['Date']) return 0; return ($a['Date'] < $b['Date'])?-1:1;} echo PHP_EOL."Sorting toots by date ..."; usort($OutArray,"ByDate"); echo PHP_EOL."Writing output file \"$OutFile\" ..."; foreach ($OutArray as $TtNr => $Toot) // Conversion of $OutArray to a plain text. {$PlainToot=PHP_EOL."--- ".$Toot['Date']." [".$TtNr."] ".$Toot['Id']; if (array_key_exists('InReplyTo',$Toot)) $PlainToot.=PHP_EOL." in reply to ".$Toot['InReplyTo']; if (array_key_exists('Boosted', $Toot)) $PlainToot.=PHP_EOL." boosted ".$Toot['Boosted']; if (array_key_exists('Attachments',$Toot)) foreach ($Toot['Attachments'] as $Attachment) $PlainToot.=PHP_EOL." attached ".$Attachment['mediaType']." ". $System.$Attachment['url']." ".$Attachment['name']; if (array_key_exists('Txt',$Toot)) $PlainToot.=PHP_EOL.$Toot['Txt']; fwrite($OutHandle,iconv("UTF-8",$OutEncoding,$PlainToot)); } fclose($OutHandle); echo PHP_EOL."Mastodon archive was converted to the output file in $OutEncoding encoding."; ?>