You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mabbs/_posts/2021-02-19-picbot.md

144 lines
7.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
layout: post
title: 如何制作一个能发好图的微信机器人
tags: [微信, 聊天, 机器人, PHP]
---
微信不好。PHP<!--more-->
# 起因
前几天,我由于图片机器人做失败了所以做了一个[聊天机器人](/2021/02/06/wechatbot.html)但是很可惜人家图灵机器人支持一键接入微信公众号当然测试号不行总而言之做那个什么聊天机器人毫无意义而且我还用的是V1的API功能根本就没发挥出来。
总之,既然目标是做图片机器人,那么就不能就聊天机器人而满足了,正好,今天看到群友分享了一个不错的[API](https://api.lolicon.app/)文档写的很清晰而且功能不错我反正也懒得去思考要怎么搞Pixiv上面的图片既然有人已经写好了那就直接用就好了。
# 怎么搞
既然图源有了那么要怎么发送图片呢既然听别人说可以用什么客服接口那就再仔细看看那个文档呗。我以前以为那个客服接口必须要生成客服账号啥的很麻烦就没怎么看后来发现好像不用而且只要用户发一句话在48小时内都可以调用这个接口给用户发消息那这么看来就很棒了啊我还以为只有5秒内被动回复一种方法这样我可以直接整个异步过去。具体API的用法可以去看[微信开放文档](https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Service_Center_messages.html#7)。
# 快点上代码
```php
<?php
$appid=微信appID;
$secret=微信appsecret;
$appkey=图灵机器人APIkey;
$apikey='Lolicon API Key';
ini_set('session.gc_maxlifetime', 7200);
ignore_user_abort(true);
set_time_limit(0);
session_id('Storage');
session_start();
if(!json_decode(file_get_contents('https://api.weixin.qq.com/cgi-bin/get_api_domain_ip?access_token='.$_SESSION['access_token']),true)['ip_list']){
$_SESSION['access_token']=json_decode(file_get_contents('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$secret),true)['access_token'];
}
if($_GET["upap"]){
define('MULTIPART_BOUNDARY', '--------------------------'.microtime(true));
$picurl=json_decode(file_get_contents('https://api.lolicon.app/setu/?r18=1&size1200=1&apikey='.$apikey),true)['data'][0]['url'];
if(!$picurl){
$picurl=json_decode(file_get_contents('https://api.lolicon.app/setu/?r18=1&size1200=1'),true)['data'][0]['url'];
}
if(!$picurl){
file_get_contents('https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.$_SESSION['access_token'] , false, stream_context_create(array('http' => array('method' => 'POST','header' => 'Content-type: application/json;charset=utf-8','content' => '{
"touser":"'.$_GET["openid"].'",
"msgtype":"text",
"text":
{
"content":"很抱歉获取失败可能是API次数达到上限请明天再试"
}
}'))));
exit();
}
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: multipart/form-data; boundary='.MULTIPART_BOUNDARY,
'content' => "--".MULTIPART_BOUNDARY."\r\n".
"Content-Disposition: filename=\"image.png\"\r\n".
"Content-Type: image/png\r\n\r\n".
file_get_contents($picurl)."\r\n".
"--".MULTIPART_BOUNDARY."--\r\n"
)
));
file_get_contents('https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.$_SESSION['access_token'] , false, stream_context_create(array('http' => array('method' => 'POST','header' => 'Content-type: application/json;charset=utf-8','content' => '{
"touser":"'.$_GET["openid"].'",
"msgtype":"image",
"image":
{
"media_id":"'.json_decode(file_get_contents('https://api.weixin.qq.com/cgi-bin/media/upload?access_token='.$_SESSION['access_token'].'&type=image', false, $context),true)['media_id'].'"
}
}'))));
exit();
}
function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = 'mayx';
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
if(checkSignature()){
if($_GET["echostr"]){
echo $_GET["echostr"];
}else{
// 加载XML内容
$content = file_get_contents("php://input");
$p = xml_parser_create();
xml_parse_into_struct($p, $content, $vals, $index);
xml_parser_free($p);
if($vals[$index['MSGTYPE'][0]]['value'] == 'text'){
if($vals[$index['CONTENT'][0]]['value'] == '来点色图'){
echo '<xml>
<ToUserName><![CDATA['.$vals[$index['FROMUSERNAME'][0]]['value'].']]></ToUserName>
<FromUserName><![CDATA['.$vals[$index['TOUSERNAME'][0]]['value'].']]></FromUserName>
<CreateTime>'.time().'</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[开始发起请求,请耐心等待]]></Content>
</xml>';
file_get_contents('https://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?upap=1&openid='.$vals[$index['FROMUSERNAME'][0]]['value'], false, stream_context_create(array('http' => array('timeout' => 0.5))));
}else{
echo '<xml>
<ToUserName><![CDATA['.$vals[$index['FROMUSERNAME'][0]]['value'].']]></ToUserName>
<FromUserName><![CDATA['.$vals[$index['TOUSERNAME'][0]]['value'].']]></FromUserName>
<CreateTime>'.time().'</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA['.json_decode(file_get_contents('https://www.tuling123.com/openapi/api', false, stream_context_create(array('http' => array('method' => 'POST','header' => 'Content-type:application/x-www-form-urlencoded','content' => http_build_query(array('key' => $appkey,'info' => $vals[$index['CONTENT'][0]]['value'],'userid' => $vals[$index['FROMUSERNAME'][0]]['value'])))))),true)['text'].']]></Content>
</xml>';
}
}
}
}else{
echo 'error';
}
```
2021.02.19更新当Lolicon API Key次数不够时会尝试不使用Key调用增加了缓存`access_token`的功能。另外以后我会自己搞一个图片API免得总是被这个每天只有300次调用的垃圾API所限制。
2021.02.21更新上次不知道怎么就脑残的用了调用次数只有500次的获取用户接口作为检查`access_token`的依据这次换了个没有上限的另外把session的回收时间改成了2个小时和接口对应。
# 怎么用?
和[上一篇](/2021/02/06/wechatbot.html#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95)一样不过有一个不一样的地方就是这里需要一个Lolicon API Key如果没有的话好像限制非常高可能一天只能调用1-2次吧有API Key好像可以每天请求300次具体怎么用可以看[他们的文档](https://api.lolicon.app/#/setu)。
API Key的申请方式是去找他们的Telegram机器人[@loliconApiBot](https://t.me/loliconApiBot)倒是还挺简单的申请出一个API和一个测试号可以供100人使用这一点还是挺不错的。
最后做好了就可以向测试号发送来点什么图?关键词可以自己在代码里改。
如果不想整图灵机器人也行,那个东西要实名还是挺麻烦的,不过这样聊天功能就不能正常工作了 ~~(谁用这个机器人是和聊天机器人聊天啊!)~~
另外PHP空间很好申请的相比Python还是非常有性价比的至少可以不用租服务器。
# 总结
这次代码用了不少有意思的特性,比如通过`file_get_contents`直接上传文件以及PHP异步之类的这个异步的功能还是我自己想出来的哦现在在百度上都不一定能搜到我这样的方法。
总之PHP还是挺有意思的。