上周我和妻子买了一台俗称“猫咪打印机”的打印机:这是一款非常便宜(不到10英镑)的热敏打印机,上面画着一张猫脸。它的官方使用方法是使用众多糟糕的应用程序之一——每家销售这类打印机的公司都会对型号进行一些调整,并推出自己的应用程序。但令我感兴趣的是,有些人已经对打印机进行了逆向工程,可以从各种平台(包括我最喜欢的网络)进行打印。我很清楚自己想用它做什么:让人们“嘟嘟嘟”地叫我,然后它就能打印出来。
我有一个型号为 MXW01 的打印机,我感觉它比较新。这意味着它无法兼容大多数库,因为它们都支持同一套模型。我以为运气不好,直到我在 GitHub 搜索中输入了型号,找到了这个项目。这个人不仅设计出了该型号的蓝牙协议,还搭建了一个图像和收据打印机的网页。这就是我编写 KnightPrint 代码的基础。
笔记
这个代码目前不在 GitHub 上。它包含 API 密钥和各种信息。等我整理好之后,会把它链接到这里。如果你正在读这篇文章,它仍然不可用。
我不断修改猫打印机代码,直到它能够渲染任意文本和图像,并在一定间隔内向端点发出请求。
一旦我完成了这项工作,我就在我的 GoToSocial 实例上设置了一个帐户@[email protected] ,获取了 API 密钥,并设置了这个非常快速的端点来获取新的提及,将图像下载到 tmp 目录,并且还有一种方法可以保存我已经打印的 toots 的 ID。
<?php
$method = $_GET [ 'type' ] ?? 'mentions' ;
$curl = curl_init ( ) ;
header ( "Content-Type: application/json" ) ;
if ( $method === 'mentions' ) {
curl_setopt_array ( $curl , array (
CURLOPT_URL => 'https://hub.7622.me/api/v1/notifications?types[]=mention' ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_ENCODING => '' ,
CURLOPT_MAXREDIRS => 10 ,
CURLOPT_TIMEOUT => 0 ,
CURLOPT_FOLLOWLOCATION => true ,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1 ,
CURLOPT_CUSTOMREQUEST => 'GET' ,
CURLOPT_HTTPHEADER => array (
'Authorization: Bearer lolnope'
) ,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3' ,
) ) ;
$response = curl_exec ( $curl ) ;
curl_close ( $curl ) ;
$data = json_decode ( $response ) ;
$ids = json_decode ( file_get_contents ( 'ids.json' ) ) ;
$data = array_filter ( array_map ( function ( $mention ) use ( $ids ) {
$printed = in_array ( $mention -> id , $ids ) ;
if ( $printed ) {
return null ; // Skip already printed mentions
}
$attachment = $mention -> status -> media_attachments [ 0 ] ?? null ;
$attachmentPath = null ;
if ( $attachment && $attachment -> type === 'image' ) {
$url = $attachment -> preview_url ;
$attachmentPath = './tmp/' . basename ( $url ) ;
if ( ! file_exists ( $attachmentPath ) ) {
ini_set ( 'user_agent' , 'KnightPrint' ) ;
file_put_contents ( $attachmentPath , file_get_contents ( $url ) ) ;
}
}
return [
'id' => $mention -> id ,
'name' => $mention -> account -> display_name ?? $mention -> account -> username ,
'account' => $mention -> account -> acct ,
'content' => strip_tags ( str_replace ( '</p><p>' , "\n\n" , $mention -> status -> content ) ) ,
'image' => $attachmentPath ? [
'url' => $attachmentPath ,
'width' => $attachment -> meta -> small -> width ?? null ,
'height' => $attachment -> meta -> small -> height ?? null ,
] : null ,
] ;
} , $data ) ) ;
echo json_encode ( $data ) ;
} else if ( $method === 'printed' ) {
$ids = json_decode ( file_get_contents ( 'ids.json' ) ) ;
$newIds = explode ( ',' , $_GET [ 'ids' ] ) ;
$ids = array_merge ( $ids , $newIds ) ;
file_put_contents ( 'ids.json' , json_encode ( $ids ) ) ;
echo json_encode ( [
'status' => 'success' ,
'message' => 'ID added successfully' ,
'ids' => $ids
] ) ;
}
然后,前端会访问这个端点,检查是否有新的 toot,将其渲染到画布上并打印出来。打印完成后,它会将 ID 发送到 API 端点,然后 API 端点会将 ID 保存到 JSON 文件中,这样我就不会重复打印相同的 toot。
然后我把它放开了:
试试这个。理论上,接下来的20分钟内(或者直到我关机之前),你发给@knightprint的任何东西,都会直接在我的小热敏打印机上打印出来。
第一批来了,一切都运行良好,但我注意到我没有在打印输出上输入此人的用户名,因此我在监听新嘟嘟声时编辑了端点:
- 'content' => strip_tags(str_replace('</p><p>', "\n\n", $mention->status->content)),
+ 'content' => strip_tags(str_replace('</p><p>', "\n\n", $mention->status->content)) . "\n\n - @" . $mention->account->acct,
大约20分钟后,我关掉它,想看看打印了什么,结果我生平第一次看到了这么长的清单,简直比我的胳膊还长。然后我又打开了它,因为觉得挺好玩的。
我会随机再次打开它,并且我还有一些其他的想法也可以通过它来实现。