微信机器人原理:
$self->_login()
$self->_init();
$self->_get_chatroom();
$self->_update_chatroom_member();
$self->update_friend();
安装路径:
/usr/local/share/perl5/Weixin
my $client = Weixin::Client->new(debug=>0);
$client->load("ShowMsg");
$client->login();
$client->on_receive_msg = sub{
my $msg = shift ;
#打印收到的消息
$client->call("ShowMsg",$msg);
#对收到的消息,以相同的内容回复
#$client->reply_msg($msg,$msg->{Content});
};
$client->on_send_msg = sub {
my ($msg,$is_success,$status) = @_;
#打印发送的消息
$client->call("ShowMsg",$msg);
};
$client->run();
1.问下 微信的$client->on_receive_msg = sub{
my $msg = shift ; 这个$msg 最初的来源在哪里的
最初的接收的消息
灰灰(308165330) 10:41:33
Weixin/Message.pm line 73
Client/Private/_sync.pm 接收消息 异步方式
$self->asyn_http_post()
$self->http_post()
异步http请求,阻塞http请求 我封装了这两个
sub asyn_http_get {
my $self = shift;
my $callback = pop;
my $ua = $self->{asyn_ua};
$ua->get(@_,sub{
my $response = shift;
$self->{cookie_jar}->save;
print $response->content(),"
" if $self->{debug};
$callback->($response);
});
}
sub http_post{
my $self = shift;
my $ua = $self->{ua};
my $res = $ua->post(@_);
$self->{cookie_jar}->save;
return (defined $res and $res->is_success)?$res->content:undef;
}
Client/Private/_send_text_msg.pm 发送消息
发异步请求 就是使用 Weixin::UserAgent 这个异步请求的类
这个异步请求的类 又是封装了 AnyEvent::HTTTP 这个模块 这个模块又是基于AnyEvent的异步来实现http起步请求的
my $client = Weixin::Client->new(debug=>0); 调用Weixin::Client 类的new方法如下,传入参数为debug=>0
sub new{
my $class = shift;
my %p = @_;
my $agent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062';
my $tmpdir = File::Spec->tmpdir();
my $cookie_filename = $p{login_file} || "$tmpdir/weixin_client_login.dat";
my $self = {
cookie_jar => HTTP::Cookies->new(hide_cookie2=>1,file=>$cookie_filename,autosave=>1),
debug => $p{debug},
_token => {},
_watchers => {},
_intervals => {},
_synccheck_error_count => 0,
_synccheck_running => 0,
_sync_running => 0,
_sync_interval => 1,
_synccheck_interval => 1,
_send_msg_interval => 4,
_last_sync_time => undef,
_last_synccheck_time => undef,
_send_message_queue => Weixin::Message::Queue->new,
_receive_message_queue => Weixin::Message::Queue->new,
_data => {
user => {},
friend => [],
chatroom => [],
},
on_run => undef,
on_receive_msg => undef,
on_send_msg => undef,
is_stop => 0,
plugin_num => 0,
plugins => {},
ua_retry_times => 5,
tmpdir => $tmpdir,
client_version => $VERSION,
};
$self->{ua} = LWP::UserAgent->new(
cookie_jar => $self->{cookie_jar},
agent => $agent,
timeout => 300,
ssl_opts => {verify_hostname => 0},
);
$self->{asyn_ua} = Weixin::UserAgent->new(
cookie_jar => $self->{cookie_jar},
agent => $agent,
request_timeout => 300,
inactivity_timeout => 300,
);
if($self->{debug}){
$self->{ua}->add_handler(request_send => sub {
my($request, $ua, $h) = @_;
print $request->as_string;
return;
});
$self->{ua}->add_handler(
response_header => sub { my($response, $ua, $h) = @_;
print $response->as_string;
return;
});
$self->{ua}->add_handler(
response_done => sub { my($response, $ua, $h) = @_;
print substr($response->content,0,1000),"
" if $response->header("content-type")=~/^text/;
return;
});
}
bless $self,$class;
$self->prepare();
return $self;
}
登录、获取好友信息等这些http请求是阻塞的,必须等待执行返回
接收消息、发送消息这些http请求是异步的 不需要阻塞在那里
这里传入的:
$class is Weixin::Client
%p is debug0
返回的对象:
$self is ------
$VAR1 = bless( {
'ua' => bless( {
'max_redirect' => 7,
'protocols_forbidden' => undef,
'show_progress' => undef,
'handlers' => {
'request_prepare' => bless( [
{
'owner' => 'LWP::UserAgent::cookie_jar',
'callback' => sub { "DUMMY" },
'line' => '/usr/share/perl5/LWP/UserAgent.pm:630'
}
], 'HTTP::Config' ),
'response_header' => bless( [
{
'owner' => 'LWP::UserAgent::parse_head',
'callback' => sub { "DUMMY" },
'm_media_type' => 'html',
'line' => '/usr/share/perl5/LWP/UserAgent.pm:609'
}
], 'HTTP::Config' ),
'response_done' => bless( [
{
'owner' => 'LWP::UserAgent::cookie_jar',
'callback' => sub { "DUMMY" },
'line' => '/usr/share/perl5/LWP/UserAgent.pm:633'
}
], 'HTTP::Config' )
},
'no_proxy' => [],
'protocols_allowed' => undef,
'use_eval' => 1,
'requests_redirectable' => [
'GET',
'HEAD'
],
'timeout' => 300,
'cookie_jar' => bless( {
'autosave' => 1,
'COOKIES' => {
'wx.qq.com' => {
'/' => {
'wxuin' => [
'0',
'1284510822',
undef,
1,
'',
1452669645,
''
],
'webwxuvid' => [
'0',
'9ee169770fb187e18f67d0876923a8c8e8fdf604d9850d7de806072c57af7ed9e9cd9c8adf120369fc1514659d14ec90',
undef,
1,
'',
1767754495,
''
],
'wxloadtime' => [
'0',
'1452394495_expired',
undef,
1,
'',
1452437951,
''
],
'mm_lang' => [
'0',
'zh_CN',
undef,
1,
'',
1452799407,
''
],
'wxpluginkey' => [
'0',
'1452396606',
undef,
1,
'',
1452453645,
''
]
}
}
},
'file' => '/tmp/weixin_client_login.dat',
'hide_cookie2' => 1
}, 'HTTP::Cookies' ),
'def_headers' => bless( {
'user-agent' => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062'
}, 'HTTP::Headers' ),
'proxy' => {},
'max_size' => undef
}, 'LWP::UserAgent' ),
'is_stop' => 0,
'_send_message_queue' => bless( {
'callback_for_get_bak' => sub { "DUMMY" },
'callback_for_get' => $VAR1->{'_send_message_queue'}{'callback_for_get_bak'},
'queue' => []
}, 'Weixin::Message::Queue' ),
'_send_msg_interval' => 4,
'tmpdir' => '/tmp',
'plugins' => {},
'on_receive_msg' => undef,
'_data' => {
'friend' => [],
'user' => {},
'chatroom' => []
},
'_last_sync_time' => undef,
'_sync_running' => 0,
'asyn_ua' => bless( {
'inactivity_timeout' => 300,
'max_redirects' => 5,
'agent' => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062',
'cookie_jar' => $VAR1->{'ua'}{'cookie_jar'},
'request_timeout' => 300
}, 'Weixin::UserAgent' ),
'_token' => {},
'_last_synccheck_time' => undef,
'_synccheck_interval' => 1,
'plugin_num' => 0,
'on_send_msg' => undef,
'debug' => 0,
'_watchers' => {},
'_synccheck_error_count' => 0,
'_intervals' => {},
'_receive_message_queue' => bless( {
'callback_for_get_bak' => sub { "DUMMY" },
'callback_for_get' => $VAR1->{'_receive_message_queue'}{'callback_for_get_bak'},
'queue' => []
}, 'Weixin::Message::Queue' ),
'_synccheck_running' => 0,
'ua_retry_times' => 5,
'on_run' => undef,
'_sync_interval' => 1,
'cookie_jar' => $VAR1->{'ua'}{'cookie_jar'},
'client_version' => '2.0'
}, 'Weixin::Client' );
load 方法:
sub load {
my $self = shift;
my @module_name = @_;
for my $module_name (@module_name){
my $module_function = undef;
if(substr($module_name,0,1) eq '+'){
substr($module_name,0,1) = "";
$module = $module_name;
}
第一个参数为对象:
$msg is ------
$VAR1 = bless( {
'ToUin' => 1284510822,
'MsgClass' => 'recv',
'CreateTime' => 1452758596,
'ToNickName' => '我',
'FromId' => '@2c33cb9d541cc8e0cd7c5ec018b56cda185aa0174f181f9d4e0136b286035a02',
'FromRemarkName' => undef,
'ToRemarkName' => undef,
'Type' => 'friend_message',
'MsgType' => 'text',
'FromNickName' => undef,
'FromUin' => undef,
'Content' => '你也147258369',
'TTL' => 5,
'ToId' => '@355da879478ba362e808fa906075a50823712e71e19f4a06ceba0ff4c56d238f',
'MsgId' => '800096966135914975'
}, 'Weixin::Message::Recv' );
接收消息的类:
Weixin::Message::Recv 这个类 来自于:
Weixin::Message::Recv
jrhmpt01:/usr/local/share/perl5/Weixin# vim Message.pm
sub _mk_ro_accessors {
my $self = shift; ### 第一个参数$self对象
my $msg =shift; ###
my $msg_pkg = shift;
no strict 'refs';
for my $field (keys %$msg){
*{__PACKAGE__ . "::${msg_pkg}::$field"} = sub{
my $obj = shift;
my $pkg = ref $obj; ##获得类名字
die "the value of "$field" in $pkg is read-only
" if @_!=0;
return $obj->{$field};
};
}
return bless $msg,__PACKAGE__."::$msg_pkg";
}
这里的当前包是Weixin::Message
1.登录接口:
https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=4fbNLiMKhA==&tip=0&r=-1570013618&_=1453268946261
微信登录接口:
my $api = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login';
_login.pm 方法:
package Weixin::Client;
use Weixin::Client::Private::_get_qrcode_uuid;
use Weixin::Client::Private::_get_qrcode_image;
use Weixin::Client::Private::_is_need_login;
1.1获取 uuid
_get_qrcode_uuid 方法:
https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=1453269277552
响应:
window.QRLogin.code = 200; window.QRLogin.uuid = "4dyqQzTV_g==";
1.2 获取二维码
https://login.weixin.qq.com/qrcode/Ab3x-F9bqw==
返回2维码
1.3
https://wx.qq.com/?&lang=zh_CN
返回帮助信息
2 _init
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-1571406762&lang=zh_CN&pass_ticket=gII3G4F43MHyoE3NXEpQGjnL%252FO4Kh9oT7L9qOJyNBqYicc6NB%252FJzkt%252F0GHZFtdRm
返回群好友信息
3._get_chatroom();
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=1453270436253&lang=zh_CN&pass_ticket=gII3G4F43MHyoE3NXEpQGjnL%252FO4Kh9oT7L9qOJyNBqYicc6NB%252FJzkt%252F0GHZFtdRm
返回聊天群及成员
4._update_chatroom_member
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact
5._update_friend
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=gII3G4F43MHyoE3NXEpQGjnL%252FO4Kh9oT7L9qOJyNBqYicc6NB%252FJzkt%252F0GHZFtdRm&r=1453270435381&seq=0&skey=@crypt_597aeefd_52e341350b71c7dae5c660c45c50eb31
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact
获取好友信息
3.
收消息:
Client/Private/_sync.pm 接收消息 异步方式
sub _sync {
my $self = shift;
return if $self->{_synccheck_running}
如果 $self->{_synccheck_running} 就直接return 什么也不干
my $callback = sub{
$self->{_sync_running} = 0;
my $response = shift;
print $response->content(),"
" if $self->{debug};
my $d = $self->json_decode($response->content());
#return if $d->{BaseResponse}{Ret}!=0;
$self->_parse_sync_data($d);
};
my $response = shift;
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=g+05x/2cwXtfEmV5&skey=@crypt_597aeefd_52e341350b71c7dae5c660c45c50eb31&lang=zh_CN
接收消息:
"AddMsgCount": 1,
"AddMsgList": [{
"MsgId": "8442920128804454773",
"FromUserName": "@78a7a53674f57a5a6070221eeb8fcf706a7aaf965ce2d205b1ec8d76597953c7",
"ToUserName": "@c2afb19006a336777800351b8f1a5142c5dde8dfd2f68b86b6cb196a76dddac1",
"MsgType": 1,
"Content": "kjk7787czcb<br/>",
4.发消息
_send_text_msg.pm
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN
post 发送消息:
{"BaseRequest":{"Uin":1284510822,"Sid":"g+05x/2cwXtfEmV5","Skey":"@crypt_597aeefd_52e341350b71c7dae5c660c45c50eb31"
,"DeviceID":"e200795958639167"},"Msg":{"Type":1,"Content":"xxxxxxx","FromUserName":"@c2afb19006a336777800351b8f1a5142c5dde8dfd2f68b86b6cb196a76dddac1"
,"ToUserName":"@@b866ff46bfe180745fea6a005cfeb9cad0ac90ae8e80acaca7f1553b6e5c3739","LocalID":"14532728152810691"
,"ClientMsgId":"14532728152810691"}}