Skip to content

Commit

Permalink
use perl mojo:weixin implement my goal
Browse files Browse the repository at this point in the history
  • Loading branch information
Archer Reilly committed Dec 13, 2016
1 parent 7566fba commit c598660
Show file tree
Hide file tree
Showing 3 changed files with 363 additions and 0 deletions.
308 changes: 308 additions & 0 deletions IRCShell.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
package Mojo::Weixin::Plugin::IRCShell;
$Mojo::Weixin::Plugin::IRCShell::PRIORITY = 99;
use strict;
use List::Util qw(first);
BEGIN{
$Mojo::Weixin::Plugin::IRCShell::has_mojo_irc_server = 0;
eval{
require Mojo::IRC::Server::Chinese;
};
$Mojo::Weixin::Plugin::IRCShell::has_mojo_irc_server = 1 if not $@;
}

my $ircd;
sub call{
my $client = shift;
my $data = shift;
$client->die("请先安装模块 Mojo::IRC::Server::Chinese") if not $Mojo::Weixin::Plugin::IRCShell::has_mojo_irc_server;
my $master_irc_user = $data->{master_irc_user} || $client->account;
#my $image_api = $data->{image_api}; # || 'http://img.vim-cn.com/';
my $image_api = $data->{image_api} || 'http://img.vim-cn.com/';
my $is_load_friend = defined $data->{load_friend}?$data->{load_friend}:1;
my @groups = ref($data->{group}) eq "ARRAY"?@{$data->{group}}:();
my %mode = ref($data->{mode}) eq "HASH"?%{$data->{mode}}:();
$ircd = Mojo::IRC::Server::Chinese->new(listen=>$data->{listen},log=>$client->log);
$ircd->on(privmsg=>sub{
my($ircd,$user,$msg) = @_;
if(substr($msg->{params}[0],0,1) eq "#" ){
my $channel_name = $msg->{params}[0];
my $content = $msg->{params}[1];
my $raw_content = $content;
my $channel = $ircd->search_channel(name=>$channel_name);
return if not defined $channel;
my $group = $client->search_group(id=>$channel->id);
return if not defined $group;
if($content=~/^([^\s]+?): /){
my $at_nick = $1;
$content =~s/^([^\s]+?): /\@$at_nick / if $ircd->search_user(nick=>$at_nick);
$raw_content = $content;
}
if($user->user ne $master_irc_user and !$user->is_localhost){
$content = $user->nick . ": $content";
#$content .= " (来自 ".$user->nick.")";
}
# 向群组里面发送图片命令解析 sendFile /tmp/dog.png
if ($content =~ m/^sendFile /) {
my @commands = split ' ', $content;
$group->send_media($commands[1]);
}
#$group->send($content,sub{
# $_[1]->from("irc");
# $_[1]->cb(sub{
# my($client,$msg,$status)=@_;
# if($status->is_success){
# if($msg->content ne $raw_content){
# $msg->content($raw_content);
# }
# }
# else{
# $user->send($user->ident,"PRIVMSG",$channel_name,$content . "[发送失败]");
# }
# });
#});
}
elsif($user->user eq $master_irc_user or $user->is_localhost){
my $nick = $msg->{params}[0];
my $content = $msg->{params}[1];
my $u = $ircd->search_user(nick=>$nick,virtual=>1);
return if not defined $u;
my $friend = $client->search_friend(id=>$u->id);
if(defined $friend){
# 检测发送文件的二级命令 sendFile /tmp/dog.png
if ($content =~ m/^sendFile /) {
my @commands = split ' ', $content;
$friend->send_media($commands[1]);
}

#$friend->send($content,sub{
# $_[1]->from("irc");
# $_[1]->cb(sub{
#my($client,$msg,$status)=@_;
#return if $status->is_success;
#$user->send($user->ident,"PRIVMSG",$nick,$content . "[发送失败]");
# });
#});
}
else{
$user->send($user->ident,"PRIVMSG",$nick,$content . "[发送失败]");
$user->send($user->ident,"PRIVMSG",$nick,"你和 [$nick] 并非好友关系");
}
}
});

my $callback = sub{
my %delete_channel = map {$_->id => $_} grep {$_->name ne "#我的好友"} $ircd->channels;
$ircd->remove_user($_) for grep {$_->is_virtual} $ircd->users;
my $friend_channel = $ircd->new_channel(name=>'#我的好友',mode=>"Pis");
if($is_load_friend){
$client->each_friend(sub{
my($client,$friend) = @_;
my $user = $ircd->search_user(nick=>$friend->displayname,virtual=>0);
if(defined $user){
$user->once(close=>sub{
my $virtual_user = $ircd->new_user(
id => $friend->id,
name => $friend->displayname . ":虚拟用户",
nick => $friend->displayname,
user => $friend->id,
virtual => 1,
);
$virtual_user->join_channel($friend_channel);
});
}
else{
my $virtual_user = $ircd->new_user(
id => $friend->id,
name => $friend->displayname . ":虚拟用户",
nick => $friend->displayname,
user => $friend->id,
virtual => 1,
);
$virtual_user->join_channel($friend_channel);
}
});
}
$client->each_group(sub{
my($client,$group) = @_;
return if(@groups and not first {$group->displayname eq $_} @groups);
my $mode = defined $mode{$group->displayname}?$mode{$group->displayname}:"Pi";
my $channel_name = '#'.$group->displayname;$channel_name=~s/\s|,|&//g;
my $channel = $ircd->search_channel(name=>$channel_name);
if(defined $channel){
delete $delete_channel{$channel->id};
$channel->id($group->id);
$channel->remove_user($_) for grep {$_->is_virtual} $channel->users;
}
else{ $ircd->new_channel(id=>$group->id,name=>'#'.$group->displayname,mode=>$mode);}
});
$ircd->remove_channel($_) for values %delete_channel;
};
$client->on(ready=>sub{
$master_irc_user = $data->{master_irc_user} || $client->account;
$callback->();
$client->on(login=>$callback);
});
$client->on(receive_message=>sub{
my($client,$msg) = @_;
if($msg->type eq "friend_message"){
my $friend = $msg->sender;
my $user = $ircd->search_user(id=>$friend->id,virtual=>1) || $ircd->search_user(nick=>$friend->displayname,virtual=>0);
my $channel = $ircd->search_channel(name=>'#我的好友') || $ircd->new_channel(name=>'#我的好友',mode=>"Pis");
return if not defined $channel;
if(not defined $user){
$user = $ircd->new_user(
id =>$friend->id,
name =>$friend->displayname . ":虚拟用户",,
user =>$friend->id,
nick =>$friend->displayname,
virtual => 1,
);
$user->join_channel($channel);
}
else{
$user->join_channel($channel) if $user->is_virtual and !$user->is_join_channel($channel);
}
for (grep { $_->user eq $master_irc_user or $_->is_localhost} grep {!$_->is_virtual} $ircd->users){
for my $line (split /\r?\n/,$msg->content){
$_->send($user->ident,"PRIVMSG",$_->nick,$line);
$user->send($user->ident,"PRIVMSG",$_->nick,$line);
}
}
}

elsif($msg->type eq "group_message"){
my $member = $msg->sender;
#return if not defined $member;
return if @groups and not first {$member->group->displayname eq $_} @groups;
my $user = $ircd->search_user(id=>$member->id,virtual=>1) || $ircd->search_user(nick=>$member->displayname,virtual=>0);
my $channel = $ircd->search_channel(id=>$member->group->id) ||
$ircd->new_channel(id=>$member->group->id,name=>'#'.$member->group->displayname,);
return if not defined $channel;
if(not defined $user){
$user=$ircd->new_user(
id =>$member->id,
name =>$member->displayname . ":虚拟用户",
user =>$member->id,
nick =>$member->displayname,
virtual => 1,
);

$user->join_channel($channel);
}
elsif($user->is_virtual){
$user->join_channel($channel) if not $user->is_join_channel($channel);
}
#else{
# #$user->join_channel($channel) if not $user->is_join_channel($channel);
#}

#接收的图片上传到图床
$client->http_post($image_api,form=>{image=>{content=>$msg->media_data}},sub{
my($link,$ua,$tx)=@_;
return unless defined $link;
return unless $link=~/https?:\/\//;
$channel->broadcast($user->ident,"PRIVMSG",$channel->name,"图片链接: $link");
}) if defined $image_api and $msg->format eq 'media';

for(grep {!$_->is_virtual} $channel->users){
my @content = split /\r?\n/,$msg->content;
if($content[0]=~/^\@([^\s]+?) /){
my $at_nick = $1;
if($ircd->search_user(nick=>$at_nick)){
$content[0] =~s/^\@([^\s]+?) //;
$_ = "$at_nick: " . $_ for @content;
}
}
for my $line (@content){
$_->send($user->ident,"PRIVMSG",$channel->name,$line);
}
}
}

});
$client->on(send_message=>sub{
my($client,$msg) = @_;
return if $msg->from eq "irc";
if($msg->type eq "friend_message"){
my $friend = $msg->receiver;
my $user = $ircd->search_user(id=>$friend->id,virtual=>1) || $ircd->search_user(nick=>$friend->displayname,virtual=>0);
my $channel = $ircd->search_channel(name=>'#我的好友') || $ircd->new_channel(name=>'#我的好友',mode=>"Pis");
if(not defined $user){
$user=$ircd->new_user(
id =>$friend->id,
name =>$friend->displayname . ":虚拟用户",
user =>$friend->id,
nick =>$friend->displayname,
virtual => 1,
);
$user->join_channel($channel);
}
elsif($user->is_virtual){
$user->join_channel($channel) if not $user->is_join_channel($channel);
}
#接收的图片上传到图床
$client->http_post($image_api,form=>{image=>{content=>$msg->media_data}},sub{
my($link,$ua,$tx)=@_;
return unless defined $link;
return unless $link=~/https?:\/\//;
$channel->broadcast($user->ident,"PRIVMSG",$channel->name,"图片链接: $link");
}) if defined $image_api and $msg->format eq 'media';

for(
grep {$_->user eq $master_irc_user or $_->is_localhost}
grep {!$_->is_virtual} $ircd->users
)
{
for my $line (split /\r?\n/,$msg->content){
$_->send($_->ident,"PRIVMSG",$user->nick,$line);
$user->send($_->ident,"PRIVMSG",$user->nick,$line);
}
}
}
elsif($msg->type eq "group_message"){
return if @groups and not first {$msg->group->displayname eq $_} @groups;
my $channel = $ircd->search_channel(id=>$msg->group->id);
return unless defined $channel;
for my $master_irc_client (
grep {$_->user eq $master_irc_user or $_->is_localhost}
grep {!$_->is_virtual} $ircd->users
){
for(grep {!$_->{virtual}} $channel->users){
my @content = split /\r?\n/,$msg->content;
if($content[0]=~/^\@([^\s]+?) /){
my $at_nick = $1;
if($ircd->search_user(nick=>$at_nick)){
$content[0] =~s/^\@([^\s]+?) //;
map {$_ = "$at_nick: " . $_} @content;
}
}
for my $line (@content){
$_->send($master_irc_client->ident,"PRIVMSG",$channel->name,$line);
}
}
}
}
});

my $property_change_callback = sub{
my($client,$object,$property,$old,$new)=@_;
if($object->is_friend){
return if $property ne "nick" and $property ne "markname";
my $user = $ircd->search_user(id=>$object->id,virtual=>1);
return unless defined $user;
$user->set_nick($object->displayname) if $object->displayname ne $user->nick;
}
elsif($object->is_group_member){
return if $property ne "nick" and $property ne "card";
my $user = $ircd->search_user(id=>$object->id,virtual=>1);
return unless defined $user;
$user->set_nick($object->displayname) if $object->displayname ne $user->nick;
}
};
$client->on("friend_property_change"=>$property_change_callback,
"group_member_property_change"=>$property_change_callback
);

$ircd->ready();
}
1;
9 changes: 9 additions & 0 deletions weixin.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env perl
use Mojo::Weixin;
my $client = Mojo::Weixin->new();
$client->load("IRCShell",data=>{
listen=>[ {host=>"127.0.0.1",port=>6667},], #可选,IRC服务器监听的地址+端口,默认0.0.0.0:6667
load_friend => 1, #默认是0 是否初始为每个好友生成irc虚拟帐号并加入频道 #我的好友
});
$client->load("ShowMsg");
$client->run();
46 changes: 46 additions & 0 deletions weixinv1.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env perl
use Mojo::Weixin;

my $client = Mojo::Weixin->new();
$client->load("IRCShell",data=>{
listen=>[ {host=>"127.0.0.1",port=>6667},], #可选,IRC服务器监听的地址+端口,默认0.0.0.0:6667
load_friend => 1, #默认是0 是否初始为每个好友生成irc虚拟帐号并加入频道 #我的好友
});
# $client->load("ShowMsg");

#ready事件触发时 表示客户端一切准备就绪:已经成功登录、已经加载完个人/好友/群信息等
#你的代码建议尽量写在 ready 事件中
$client->on(ready=>sub{
my $client = shift;

#设置接收消息事件的回调函数,在回调函数中对消息以相同内容进行回复
$client->on(receive_message=>sub{
my ($client,$msg)=@_;
# $msg->reply($msg->content); #已以相同内容回复接收到的消息
#你也可以使用$msg->dump() 来打印消息结构
# print $msg->dump()
if($msg->type eq "friend_message"){#接收到好友消息
my $friend = $msg->sender; #获取到该好友对象
my $rcvMsg = $friend->displayname . ":" . $msg->content;
system("printf '\7'");
system("notify-send " . $rcvMsg);
print $rcvMsg;
# print "我的好友:" . $friend->displayname . "给我发了一个消息,消息的内容是:" . $msg->content;
}
elsif($msg->type eq "group_message"){#接收到群消息
my $group = $msg->group; #获取到消息对应的群组对象
my $sender = $msg->sender; #获取到发送该消息的群成员对象

print $sender->displayname . "在群:", $group->displayname . "中发了一条消息,消息的内容是:" . $msg->content;
}
elsif($msg->type eq "group_notice"){
my $group = $msg->group; #获取到消息对应的群组对象
print "在群:", $group->displayname . "中收到了一条群提示消息,消息的内容是:" . $msg->content;
}
});

#你的其他代码写在此处

});

$client->run();

0 comments on commit c598660

Please sign in to comment.