Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation
This project
Loading...
Sign in
hfpp2012
/
vbot
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit b3bfcfae
authored
Mar 16, 2017
by
HanSon
Committed by
GitHub
Mar 16, 2017
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
Merge pull request #50 from HanSon/dev
🎲
优化群控功能
2 parents
db06d623
cdd3479a
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
404 additions
and
138 deletions
README.md
example/index.php
src/Collections/Contact.php
src/Collections/ContactFactory.php
src/Collections/Group.php
src/Collections/Member.php
src/Core/Http.php
src/Core/MessageFactory.php
src/Core/MessageHandler.php
src/Core/Server.php
src/Core/Sync.php
src/Message/Entity/Emoticon.php
src/Message/Entity/GroupChange.php
src/Message/Entity/Image.php
src/Message/Entity/NewFriend.php
src/Message/Entity/Text.php
src/Message/Entity/Video.php
src/Message/UploadAble.php
src/Support/Console.php
README.md
View file @
b3bfcfa
...
...
@@ -31,13 +31,22 @@ PS:运行后二维码将保存于设置的缓存目录,命名为qr.png,控
**请在terminal运行!请在terminal运行!请在terminal运行!**
## 体验
<img
src=
"https://ws2.sinaimg.cn/large/685b97a1gy1fdordpa0cgj20e80e811z.jpg"
height=
"320"
>
扫码后,验证输入“上山打老虎”即可自动加为好友并且拉入vbot群。
vbot并非24小时执行,有时会因为开发调试等原因暂停功能。如果碰巧遇到关闭情况,可加Q群 492548647 了解开放时间。执行后发送“拉我”即可自动邀请进群。
vbot示例源码为 https://github.com/HanSon/vbot/blob/master/example/index.php
## 文档
详细文档在
[
wiki
](
https://github.com/HanSon/vbot/wiki
)
中
### 例子
[
所有类型例子
](
https://github.com/HanSon/vbot/blob/master/example/index.php
)
### 小DEMO
[
红包提醒
](
https://github.com/HanSon/vbot/blob/master/example/hongbao.php
)
...
...
example/index.php
View file @
b3bfcfa
...
...
@@ -35,7 +35,8 @@ $robot = new Vbot([
]);
// 图灵自动回复
function
reply
(
$str
){
function
reply
(
$str
)
{
return
http
()
->
post
(
'http://www.tuling123.com/openapi/api'
,
[
'key'
=>
'1dce02aef026258eff69635a06b0ab7d'
,
'info'
=>
$str
...
...
@@ -43,153 +44,244 @@ function reply($str){
}
// 设置管理员
function
isAdmin
(
$message
)
{
$adminAlias
=
'hanson1994'
;
if
(
in_array
(
$message
->
fromType
,
[
'Contact'
,
'Group'
]))
{
if
(
$message
->
fromType
===
'Contact'
)
{
return
$message
->
from
[
'Alias'
]
===
$adminAlias
;
}
else
{
return
isset
(
$message
->
sender
[
'Alias'
])
&&
$message
->
sender
[
'Alias'
]
===
$adminAlias
;
}
}
return
false
;
}
$groupMap
=
[
[
'nickname'
=>
'vbot 测试群'
,
'id'
=>
1
]
];
$robot
->
server
->
setOnceHandler
(
function
()
use
(
$groupMap
)
{
group
()
->
each
(
function
(
$group
,
$key
)
use
(
$groupMap
)
{
foreach
(
$groupMap
as
$map
)
{
if
(
$group
[
'NickName'
]
===
$map
[
'nickname'
])
{
$group
[
'id'
]
=
$map
[
'id'
];
$groupMap
[
$key
]
=
$map
[
'id'
];
group
()
->
setMap
(
$key
,
$map
[
'id'
]);
}
}
return
$group
;
});
});
$robot
->
server
->
setMessageHandler
(
function
(
$message
)
use
(
$path
)
{
/** @var $message Message */
// 位置信息 返回位置文字
if
(
$message
instanceof
Location
)
{
/** @var $message Location */
Text
::
send
(
'地图链接:'
.
$message
->
from
[
'UserName'
],
$message
->
url
);
return
'位置:'
.
$message
;
Text
::
send
(
'地图链接:'
.
$message
->
from
[
'UserName'
],
$message
->
url
);
return
'位置:'
.
$message
;
}
// 文字信息
if
(
$message
instanceof
Text
)
{
/** @var $message Text */
if
(
str_contains
(
$message
->
content
,
'vbot'
)
&&
!
$message
->
isAt
)
{
return
"你好,我叫vbot,我爸是HanSon
\n
我的项目地址是 https://github.com/HanSon/vbot
\n
欢迎来给我star!"
;
}
// 联系人自动回复
if
(
$message
->
fromType
===
'Contact'
)
{
if
(
$message
->
content
===
'拉我'
)
{
$username
=
group
()
->
getUsernameById
(
1
);
group
()
->
addMember
(
$username
,
$message
->
from
[
'UserName'
]);
}
if
(
$message
->
content
===
'测试'
){
$username
=
group
()
->
getUsernameById
(
1
);
print_r
(
$username
);
print_r
(
group
()
->
get
(
$username
));
}
return
reply
(
$message
->
content
);
// 群组@我回复
}
elseif
(
$message
->
fromType
===
'Group'
&&
$message
->
isAt
)
{
return
reply
(
$message
->
content
);
}
elseif
(
$message
->
fromType
===
'Group'
)
{
if
(
str_contains
(
$message
->
content
,
'设置群名称'
)
&&
isAdmin
(
$message
))
{
group
()
->
setGroupName
(
$message
->
from
[
'UserName'
],
str_replace
(
'设置群名称'
,
''
,
$message
->
content
));
}
if
(
str_contains
(
$message
->
content
,
'搜人'
)
&&
isAdmin
(
$message
))
{
$nickname
=
str_replace
(
'搜人'
,
''
,
$message
->
content
);
$members
=
group
()
->
getMembersByNickname
(
$message
->
from
[
'UserName'
],
$nickname
,
true
);
$result
=
'搜索结果 数量:'
.
count
(
$members
)
.
"
\n
"
;
foreach
(
$members
as
$member
)
{
$result
.=
$member
[
'NickName'
]
.
' '
.
$member
[
'UserName'
]
.
"
\n
"
;
}
return
$result
;
}
if
(
str_contains
(
$message
->
content
,
'踢人'
)
&&
isAdmin
(
$message
))
{
$username
=
str_replace
(
'踢人'
,
''
,
$message
->
content
);
group
()
->
deleteMember
(
$message
->
from
[
'UserName'
],
$username
);
}
if
(
str_contains
(
$message
->
content
,
'踢我'
)
&&
$message
->
isAt
)
{
Text
::
send
(
$message
->
from
[
'UserName'
],
'拜拜 '
.
$message
->
sender
[
'NickName'
]);
group
()
->
deleteMember
(
$message
->
from
[
'UserName'
],
$message
->
sender
[
'UserName'
]);
return
'vbot 从未见过这么犯贱的人'
;
}
if
(
$message
->
isAt
)
{
return
reply
(
$message
->
content
);
}
}
}
// 图片信息 返回接收到的图片
if
(
$message
instanceof
Image
)
{
return
$message
;
//
return $message;
}
// 视频信息 返回接收到的视频
if
(
$message
instanceof
Video
)
{
return
$message
;
//
return $message;
}
// 表情信息 返回接收到的表情
if
(
$message
instanceof
Emoticon
)
{
return
$message
;
Emoticon
::
sendRandom
(
$message
->
from
[
'UserName'
])
;
}
// 语音消息
if
(
$message
instanceof
Voice
)
{
if
(
$message
instanceof
Voice
)
{
/** @var $message Voice */
return
'收到一条语音并下载在'
.
$message
::
getPath
(
$message
::
$folder
)
.
"/
{
$message
->
msg
[
'MsgId'
]
}
.mp3"
;
//
return '收到一条语音并下载在' . $message::getPath($message::$folder) . "/{$message->msg['MsgId']}.mp3";
}
// 撤回信息
if
(
$message
instanceof
Recall
&&
$message
->
msg
[
'FromUserName'
]
!==
myself
()
->
username
)
{
/** @var $message Recall */
if
(
$message
->
origin
instanceof
Image
)
{
if
(
$message
->
origin
instanceof
Image
)
{
Text
::
send
(
$message
->
msg
[
'FromUserName'
],
"
{
$message
->
nickname
}
撤回了一张照片"
);
Image
::
sendByMsgId
(
$message
->
msg
[
'FromUserName'
],
$message
->
origin
->
msg
[
'MsgId'
]);
}
elseif
(
$message
->
origin
instanceof
Emoticon
)
{
}
elseif
(
$message
->
origin
instanceof
Emoticon
)
{
Text
::
send
(
$message
->
msg
[
'FromUserName'
],
"
{
$message
->
nickname
}
撤回了一个表情"
);
Emoticon
::
sendByMsgId
(
$message
->
msg
[
'FromUserName'
],
$message
->
origin
->
msg
[
'MsgId'
]);
}
elseif
(
$message
->
origin
instanceof
Video
)
{
}
elseif
(
$message
->
origin
instanceof
Video
)
{
Text
::
send
(
$message
->
msg
[
'FromUserName'
],
"
{
$message
->
nickname
}
撤回了一个视频"
);
Video
::
sendByMsgId
(
$message
->
msg
[
'FromUserName'
],
$message
->
origin
->
msg
[
'MsgId'
]);
}
elseif
(
$message
->
origin
instanceof
Voice
)
{
}
elseif
(
$message
->
origin
instanceof
Voice
)
{
Text
::
send
(
$message
->
msg
[
'FromUserName'
],
"
{
$message
->
nickname
}
撤回了一条语音"
);
}
else
{
}
else
{
Text
::
send
(
$message
->
msg
[
'FromUserName'
],
"
{
$message
->
nickname
}
撤回了一条信息
\"
{
$message
->
origin
->
msg
[
'Content'
]
}
\"
"
);
}
}
// 红包信息
if
(
$message
instanceof
RedPacket
)
{
if
(
$message
instanceof
RedPacket
)
{
// do something to notify if you want ...
return
$message
->
content
.
' 来自 '
.
$message
->
from
[
'NickName'
];
return
$message
->
content
.
' 来自 '
.
$message
->
from
[
'NickName'
];
}
// 转账信息
if
(
$message
instanceof
Transfer
)
{
if
(
$message
instanceof
Transfer
)
{
/** @var $message Transfer */
return
$message
->
content
.
' 收到金额 '
.
$message
->
fee
;
}
// 推荐名片信息
if
(
$message
instanceof
Recommend
)
{
if
(
$message
instanceof
Recommend
)
{
/** @var $message Recommend */
if
(
$message
->
isOfficial
)
{
if
(
$message
->
isOfficial
)
{
return
$message
->
from
[
'NickName'
]
.
' 向你推荐了公众号 '
.
$message
->
province
.
$message
->
city
.
"
{
$message
->
info
[
'NickName'
]
}
公众号信息:
{
$message
->
description
}
"
;
}
else
{
}
else
{
return
$message
->
from
[
'NickName'
]
.
' 向你推荐了 '
.
$message
->
province
.
$message
->
city
.
"
{
$message
->
info
[
'NickName'
]
}
头像链接:
{
$message
->
bigAvatar
}
"
;
}
}
// 请求添加信息
if
(
$message
instanceof
RequestFriend
)
{
if
(
$message
instanceof
RequestFriend
)
{
/** @var $message RequestFriend */
$groupUsername
=
group
()
->
getGroupsByNickname
(
'芬芬'
,
true
)
->
first
()[
'UserName'
];
Text
::
send
(
$groupUsername
,
"
{
$message
->
info
[
'NickName'
]
}
请求添加好友
\"
{
$message
->
info
[
'Content'
]
}
\"
"
);
if
(
$message
->
info
[
'Content'
]
===
'上山打老虎'
)
{
if
(
$message
->
info
[
'Content'
]
===
'上山打老虎'
)
{
Text
::
send
(
$groupUsername
,
'暗号正确'
);
$message
->
verifyUser
(
$message
::
VIA
);
}
else
{
}
else
{
Text
::
send
(
$groupUsername
,
'暗号错误'
);
}
}
// 分享信息
if
(
$message
instanceof
Share
)
{
if
(
$message
instanceof
Share
)
{
/** @var $message Share */
$reply
=
"收到分享
\n
标题:
{
$message
->
title
}
\n
描述:
{
$message
->
description
}
\n
链接:
{
$message
->
url
}
"
;
if
(
$message
->
app
)
{
if
(
$message
->
app
)
{
$reply
.=
"
\n
来源APP:
{
$message
->
app
}
"
;
}
return
$reply
;
}
// 分享小程序信息
if
(
$message
instanceof
Mina
)
{
if
(
$message
instanceof
Mina
)
{
/** @var $message Mina */
$reply
=
"收到小程序
\n
小程序名词:
{
$message
->
title
}
\n
链接:
{
$message
->
url
}
"
;
return
$reply
;
}
// 公众号推送信息
if
(
$message
instanceof
Official
)
{
if
(
$message
instanceof
Official
)
{
/** @var $message Official */
$reply
=
"收到公众号推送
\n
标题:
{
$message
->
title
}
\n
描述:
{
$message
->
description
}
\n
链接:
{
$message
->
url
}
\n
来源公众号名称:
{
$message
->
app
}
"
;
return
$reply
;
}
// 手机点击聊天事件
if
(
$message
instanceof
Touch
)
{
Text
::
send
(
$message
->
msg
[
'ToUserName'
],
"我点击了此聊天"
);
if
(
$message
instanceof
Touch
)
{
//
Text::send($message->msg['ToUserName'], "我点击了此聊天");
}
// 新增好友
if
(
$message
instanceof
\Hanson\Vbot\Message\Entity\NewFriend
){
\Hanson\Vbot\Support\Console
::
log
(
'新加好友:'
.
$message
->
from
[
'NickName'
]);
if
(
$message
instanceof
\Hanson\Vbot\Message\Entity\NewFriend
)
{
\Hanson\Vbot\Support\Console
::
debug
(
'新加好友:'
.
$message
->
from
[
'NickName'
]);
Text
::
send
(
$message
->
from
[
'UserName'
],
"客官,等你很久了!感谢跟 vbot 交朋友,如果可以帮我点个star,谢谢了!https://github.com/HanSon/vbot"
);
group
()
->
addMember
(
group
()
->
getUsernameById
(
1
),
$message
->
from
[
'UserName'
]);
return
'现在拉你进去vbot的测试群,进去后为了避免轰炸记得设置免骚扰哦!如果被不小心踢出群,跟我说声“拉我”我就会拉你进群的了。'
;
}
// 群组变动
if
(
$message
instanceof
GroupChange
)
{
if
(
$message
instanceof
GroupChange
)
{
/** @var $message GroupChange */
if
(
$message
->
action
===
'ADD'
){
\Hanson\Vbot\Support\Console
::
log
(
'新人进群'
);
return
$message
->
content
;
}
elseif
(
$message
->
action
===
'REMOVE'
){
\Hanson\Vbot\Support\Console
::
log
(
'群主踢人了'
);
return
$message
->
content
;
}
elseif
(
$message
->
action
===
'RENAME'
){
\Hanson\Vbot\Support\Console
::
log
(
$message
->
from
[
'NickName'
]
.
' 改名为 '
.
$message
->
rename
);
if
(
$message
->
action
===
'ADD'
)
{
\Hanson\Vbot\Support\Console
::
debug
(
'新人进群'
);
return
'欢迎新人 '
.
$message
->
nickname
;
}
elseif
(
$message
->
action
===
'REMOVE'
)
{
\Hanson\Vbot\Support\Console
::
debug
(
'群主踢人了'
);
return
$message
->
content
;
}
elseif
(
$message
->
action
===
'RENAME'
)
{
// \Hanson\Vbot\Support\Console::log($message->from['NickName'] . ' 改名为 ' . $message->rename);
if
(
group
()
->
getUsernameById
(
1
)
==
$message
->
from
[
'UserName'
]
&&
$message
->
rename
!==
'vbot 测试群'
)
{
group
()
->
setGroupName
(
$message
->
from
[
'UserName'
],
'vbot 测试群'
);
return
'行不改名,坐不改姓!'
;
}
}
elseif
(
$message
->
action
===
'BE_REMOVE'
)
{
\Hanson\Vbot\Support\Console
::
debug
(
'你被踢出了群 '
.
$message
->
group
[
'NickName'
]);
}
elseif
(
$message
->
action
===
'INVITE'
)
{
\Hanson\Vbot\Support\Console
::
debug
(
'你被邀请进群 '
.
$message
->
from
[
'NickName'
]);
}
}
...
...
@@ -197,11 +289,11 @@ $robot->server->setMessageHandler(function ($message) use ($path) {
});
$robot
->
server
->
setExitHandler
(
function
()
{
$robot
->
server
->
setExitHandler
(
function
()
{
\Hanson\Vbot\Support\Console
::
log
(
'其他设备登录'
);
});
$robot
->
server
->
setExceptionHandler
(
function
()
{
$robot
->
server
->
setExceptionHandler
(
function
()
{
\Hanson\Vbot\Support\Console
::
log
(
'异常退出'
);
});
...
...
src/Collections/Contact.php
View file @
b3bfcfa
...
...
@@ -26,7 +26,7 @@ class Contact extends Collection
*/
public
static
function
getInstance
()
{
if
(
static
::
$instance
===
null
)
{
if
(
static
::
$instance
===
null
)
{
static
::
$instance
=
new
Contact
();
}
...
...
@@ -41,8 +41,8 @@ class Contact extends Collection
*/
public
function
getContactById
(
$id
)
{
return
$this
->
filter
(
function
(
$item
,
$key
)
use
(
$id
)
{
if
(
$item
[
'Alias'
]
===
$id
)
{
return
$this
->
filter
(
function
(
$item
,
$key
)
use
(
$id
)
{
if
(
$item
[
'Alias'
]
===
$id
)
{
return
true
;
}
})
->
first
();
...
...
@@ -56,22 +56,23 @@ class Contact extends Collection
*/
public
function
getUsernameById
(
$id
)
{
return
$this
->
search
(
function
(
$item
,
$key
)
use
(
$id
)
{
if
(
$item
[
'Alias'
]
===
$id
)
{
return
$this
->
search
(
function
(
$item
,
$key
)
use
(
$id
)
{
if
(
$item
[
'Alias'
]
===
$id
)
{
return
true
;
}
});
}
/**
* 根据通讯录中的备注获取通讯对象
*
* @param $id
* @return mixed
*/
public
function
getUsernameByRemarkName
(
$id
)
public
function
getUsernameByRemarkName
(
$id
)
{
return
$this
->
search
(
function
(
$item
,
$key
)
use
(
$id
)
{
if
(
$item
[
'RemarkName'
]
===
$id
)
{
return
$this
->
search
(
function
(
$item
,
$key
)
use
(
$id
)
{
if
(
$item
[
'RemarkName'
]
===
$id
)
{
return
true
;
}
});
...
...
@@ -81,12 +82,15 @@ class Contact extends Collection
* 根据通讯录中的昵称获取通讯对象
*
* @param $nickname
* @param bool $blur
* @return mixed
*/
public
function
getUsernameByNickname
(
$nickname
)
public
function
getUsernameByNickname
(
$nickname
,
$blur
=
false
)
{
return
$this
->
search
(
function
(
$item
,
$key
)
use
(
$nickname
){
if
(
$item
[
'NickName'
]
===
$nickname
){
return
$this
->
search
(
function
(
$item
,
$key
)
use
(
$nickname
,
$blur
)
{
if
(
$blur
&&
str_contains
(
$item
[
'NickName'
],
$nickname
))
{
return
true
;
}
elseif
(
!
$blur
&&
$item
[
'NickName'
]
===
$nickname
)
{
return
true
;
}
});
...
...
@@ -113,7 +117,7 @@ class Contact extends Collection
$result
=
http
()
->
json
(
$url
,
[
'UserName'
=>
$username
,
'CmdId'
=>
3
,
'OP'
=>
(
int
)
$isStick
,
'OP'
=>
(
int
)
$isStick
,
'BaseRequest'
=>
server
()
->
baseRequest
],
true
);
...
...
src/Collections/ContactFactory.php
View file @
b3bfcfa
...
...
@@ -34,11 +34,11 @@ class ContactFactory
$this
->
makeContactList
();
$contact
=
contact
()
->
get
(
myself
()
->
username
);
myself
()
->
alias
=
isset
(
$contact
[
'Alias'
])
?
$contact
[
'Alias'
]
:
myself
()
->
nickname
?
:
myself
()
->
username
;
myself
()
->
alias
=
isset
(
$contact
[
'Alias'
])
?
$contact
[
'Alias'
]
:
myself
()
->
nickname
?:
myself
()
->
username
;
$this
->
getBatchGroupMembers
();
if
(
server
()
->
config
[
'debug'
])
{
if
(
server
()
->
config
[
'debug'
])
{
FileManager
::
download
(
'contact.json'
,
json_encode
(
contact
()
->
all
()));
FileManager
::
download
(
'member.json'
,
json_encode
(
member
()
->
all
()));
FileManager
::
download
(
'group.json'
,
json_encode
(
group
()
->
all
()));
...
...
@@ -56,23 +56,23 @@ class ContactFactory
$url
=
sprintf
(
server
()
->
baseUri
.
'/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s&seq=%s'
,
server
()
->
passTicket
,
server
()
->
skey
,
time
(),
$seq
);
$result
=
http
()
->
json
(
$url
,
[],
true
);
$memberList
=
$result
[
'MemberList'
];
$seq
=
$result
[
'Seq'
];
foreach
(
$memberList
as
$contact
)
{
if
(
official
()
->
isOfficial
(
$contact
[
'VerifyFlag'
])){
#公众号
Official
::
getInstance
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
elseif
(
in_array
(
$contact
[
'UserName'
],
static
::
SPECIAL_USERS
)){
# 特殊账户
Special
::
getInstance
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
elseif
(
strstr
(
$contact
[
'UserName'
],
'@@'
)
!==
false
){
# 群聊
group
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
else
{
contact
()
->
put
(
$contact
[
'UserName'
],
$contact
);
if
(
isset
(
$result
[
'MemberList'
])
&&
$result
[
'MemberList'
])
{
foreach
(
$result
[
'MemberList'
]
as
$contact
)
{
if
(
official
()
->
isOfficial
(
$contact
[
'VerifyFlag'
]))
{
#公众号
Official
::
getInstance
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
elseif
(
in_array
(
$contact
[
'UserName'
],
static
::
SPECIAL_USERS
))
{
# 特殊账户
Special
::
getInstance
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
elseif
(
strstr
(
$contact
[
'UserName'
],
'@@'
)
!==
false
)
{
# 群聊
group
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
else
{
contact
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
}
}
if
(
$seq
!=
0
)
{
$this
->
makeContactList
(
$
seq
);
if
(
isset
(
$result
[
'Seq'
])
&&
$result
[
'Seq'
]
!=
0
)
{
$this
->
makeContactList
(
$
result
[
'Seq'
]
);
}
}
...
...
@@ -84,7 +84,7 @@ class ContactFactory
$url
=
sprintf
(
server
()
->
baseUri
.
'/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s'
,
time
(),
server
()
->
passTicket
);
$list
=
[];
group
()
->
each
(
function
(
$item
,
$key
)
use
(
&
$list
)
{
group
()
->
each
(
function
(
$item
,
$key
)
use
(
&
$list
)
{
$list
[]
=
[
'UserName'
=>
$key
,
'EncryChatRoomId'
=>
''
];
});
...
...
@@ -104,13 +104,15 @@ class ContactFactory
*/
private
function
initGroupMembers
(
$array
)
{
foreach
(
$array
[
'ContactList'
]
as
$group
)
{
$groupAccount
=
group
()
->
get
(
$group
[
'UserName'
]);
$groupAccount
[
'MemberList'
]
=
$group
[
'MemberList'
];
$groupAccount
[
'ChatRoomId'
]
=
$group
[
'EncryChatRoomId'
];
group
()
->
put
(
$group
[
'UserName'
],
$groupAccount
);
foreach
(
$group
[
'MemberList'
]
as
$member
)
{
member
()
->
put
(
$member
[
'UserName'
],
$member
);
if
(
isset
(
$array
[
'ContactList'
])
&&
$array
[
'ContactList'
])
{
foreach
(
$array
[
'ContactList'
]
as
$group
)
{
$groupAccount
=
group
()
->
get
(
$group
[
'UserName'
]);
$groupAccount
[
'MemberList'
]
=
$group
[
'MemberList'
];
$groupAccount
[
'ChatRoomId'
]
=
$group
[
'EncryChatRoomId'
];
group
()
->
put
(
$group
[
'UserName'
],
$groupAccount
);
foreach
(
$group
[
'MemberList'
]
as
$member
)
{
member
()
->
put
(
$member
[
'UserName'
],
$member
);
}
}
}
...
...
src/Collections/Group.php
View file @
b3bfcfa
...
...
@@ -18,6 +18,13 @@ class Group extends Collection
static
$instance
=
null
;
/**
* username => id
*
* @var array
*/
public
$map
=
[];
/**
* create a single instance
*
* @return Group
...
...
@@ -62,6 +69,68 @@ class Group extends Collection
}
/**
* 根据通讯录中的昵称获取通讯对象
*
* @param $nickname
* @return mixed
*/
public
function
getUsernameByNickname
(
$nickname
)
{
return
$this
->
search
(
function
(
$item
,
$key
)
use
(
$nickname
){
if
(
$item
[
'NickName'
]
===
$nickname
){
return
true
;
}
});
}
/**
* 根据昵称搜索群成员
*
* @param $groupUsername
* @param $memberNickname
* @param bool $blur
* @return array
*/
public
function
getMembersByNickname
(
$groupUsername
,
$memberNickname
,
$blur
=
false
)
{
$members
=
$this
->
get
(
$groupUsername
);
$result
=
[];
foreach
(
$members
[
'MemberList'
]
as
$member
)
{
if
(
$blur
&&
str_contains
(
$member
[
'NickName'
],
$memberNickname
))
{
$result
[]
=
$member
;
}
elseif
(
!
$blur
&&
$member
[
'NickName'
]
===
$memberNickname
)
{
$result
[]
=
$member
;
}
}
return
$result
;
}
/**
* 根据ID获取群username
*
* @param $id
* @return mixed
*/
public
function
getUsernameById
(
$id
)
{
return
array_search
(
$id
,
$this
->
map
);
}
/**
* 设置map
*
* @param $username
* @param $id
*/
public
function
setMap
(
$username
,
$id
)
{
$this
->
map
[
$username
]
=
$id
;
}
/**
* 创建群聊天
*
* @param array $contacts
...
...
src/Collections/Member.php
View file @
b3bfcfa
...
...
@@ -26,7 +26,7 @@ class Member extends Collection
*/
public
static
function
getInstance
()
{
if
(
static
::
$instance
===
null
)
{
if
(
static
::
$instance
===
null
)
{
static
::
$instance
=
new
Member
();
}
...
...
src/Core/Http.php
View file @
b3bfcfa
...
...
@@ -50,9 +50,11 @@ class Http
return
$array
?
json_decode
(
$content
,
true
)
:
$content
;
}
public
function
json
(
$url
,
$
options
=
[],
$array
=
false
)
public
function
json
(
$url
,
$
params
=
[],
$array
=
false
,
$extra
=
[]
)
{
$content
=
$this
->
request
(
$url
,
'POST'
,
[
'json'
=>
$options
]);
$params
=
array_merge
([
'json'
=>
$params
],
$extra
);
$content
=
$this
->
request
(
$url
,
'POST'
,
$params
);
return
$array
?
json_decode
(
$content
,
true
)
:
$content
;
}
...
...
@@ -86,15 +88,9 @@ class Http
*/
public
function
request
(
$url
,
$method
=
'GET'
,
$options
=
[])
{
try
{
$response
=
$this
->
getClient
()
->
request
(
$method
,
$url
,
$options
);
return
$response
->
getBody
()
->
getContents
();
}
catch
(
\Exception
$e
){
Console
::
log
(
'http链接失败:'
.
$e
->
getMessage
(),
Console
::
ERROR
);
Console
::
log
(
'错误URL:'
.
$url
,
Console
::
ERROR
);
}
$response
=
$this
->
getClient
()
->
request
(
$method
,
$url
,
$options
);
return
null
;
return
$response
->
getBody
()
->
getContents
()
;
}
...
...
src/Core/MessageFactory.php
View file @
b3bfcfa
...
...
@@ -68,7 +68,7 @@ class MessageFactory
else
if
(
str_contains
(
$msg
[
'Content'
],
'添加'
)
||
str_contains
(
$msg
[
'Content'
],
'have added'
)
||
str_contains
(
$msg
[
'Content'
],
'打招呼'
)){
# 添加好友
return
new
NewFriend
(
$msg
);
}
else
if
(
str_contains
(
$msg
[
'Content'
],
'加入了群聊'
)
||
str_contains
(
$msg
[
'Content'
],
'移出了群聊'
)
||
str_contains
(
$msg
[
'Content'
],
'改群名为'
)){
}
else
if
(
str_contains
(
$msg
[
'Content'
],
'加入了群聊'
)
||
str_contains
(
$msg
[
'Content'
],
'移出了群聊'
)
||
str_contains
(
$msg
[
'Content'
],
'改群名为'
)
||
str_contains
(
$msg
[
'Content'
],
'移出群聊'
)
||
str_contains
(
$msg
[
'Content'
],
'邀请你'
)
){
return
new
GroupChange
(
$msg
);
}
break
;
...
...
src/Core/MessageHandler.php
View file @
b3bfcfa
...
...
@@ -32,6 +32,8 @@ class MessageHandler
private
$exceptionHandler
;
private
$onceHandler
;
private
$sync
;
private
$messageFactory
;
...
...
@@ -49,7 +51,7 @@ class MessageHandler
*/
public
static
function
getInstance
()
{
if
(
static
::
$instance
===
null
)
{
if
(
static
::
$instance
===
null
)
{
static
::
$instance
=
new
MessageHandler
();
}
...
...
@@ -64,7 +66,7 @@ class MessageHandler
*/
public
function
setMessageHandler
(
Closure
$closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
throw
new
\Exception
(
'message handler must be a closure!'
);
}
...
...
@@ -79,7 +81,7 @@ class MessageHandler
*/
public
function
setCustomHandler
(
Closure
$closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
throw
new
\Exception
(
'custom handler must be a closure!'
);
}
...
...
@@ -94,7 +96,7 @@ class MessageHandler
*/
public
function
setExitHandler
(
Closure
$closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
throw
new
\Exception
(
'exit handler must be a closure!'
);
}
...
...
@@ -109,7 +111,7 @@ class MessageHandler
*/
public
function
setExceptionHandler
(
Closure
$closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
throw
new
\Exception
(
'exit handler must be a closure!'
);
}
...
...
@@ -117,29 +119,48 @@ class MessageHandler
}
/**
* 执行一次的处理器
*
* @param Closure $closure
* @throws \Exception
*/
public
function
setOnceHandler
(
Closure
$closure
)
{
if
(
!
$closure
instanceof
Closure
)
{
throw
new
\Exception
(
'exit handler must be a closure!'
);
}
$this
->
onceHandler
=
$closure
;
}
/**
* 轮询消息API接口
*/
public
function
listen
()
{
while
(
true
){
if
(
$this
->
customHandler
instanceof
Closure
){
if
(
$this
->
onceHandler
instanceof
Closure
)
{
call_user_func_array
(
$this
->
onceHandler
,
[]);
}
while
(
true
)
{
if
(
$this
->
customHandler
instanceof
Closure
)
{
call_user_func_array
(
$this
->
customHandler
,
[]);
}
$time
=
time
();
list
(
$retCode
,
$selector
)
=
$this
->
sync
->
checkSync
();
if
(
in_array
(
$retCode
,
[
'1100'
,
'1101'
]))
{
# 微信客户端上登出或者其他设备登录
if
(
in_array
(
$retCode
,
[
'1100'
,
'1101'
]))
{
# 微信客户端上登出或者其他设备登录
Console
::
log
(
'微信客户端正常退出'
);
if
(
$this
->
exitHandler
)
{
if
(
$this
->
exitHandler
)
{
call_user_func_array
(
$this
->
exitHandler
,
[]);
}
break
;
}
elseif
(
$retCode
==
0
)
{
}
elseif
(
$retCode
==
0
)
{
$this
->
handlerMessage
(
$selector
);
}
else
{
}
else
{
Console
::
log
(
'微信客户端异常退出'
);
if
(
$this
->
exceptionHandler
)
{
if
(
$this
->
exceptionHandler
)
{
call_user_func_array
(
$this
->
exitHandler
,
[]);
}
break
;
...
...
@@ -157,27 +178,37 @@ class MessageHandler
*/
private
function
handlerMessage
(
$selector
)
{
if
(
$selector
===
0
)
{
if
(
$selector
===
0
)
{
return
;
}
$message
=
$this
->
sync
->
sync
();
if
(
$message
[
'AddMsgList'
]){
if
(
count
(
$message
[
'ModContactList'
])
>
0
)
{
foreach
(
$message
[
'ModContactList'
]
as
$contact
)
{
if
(
str_contains
(
$contact
[
'UserName'
],
'@@'
))
{
group
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
else
{
contact
()
->
put
(
$contact
[
'UserName'
],
$contact
);
}
}
}
if
(
$message
[
'AddMsgList'
])
{
foreach
(
$message
[
'AddMsgList'
]
as
$msg
)
{
$content
=
$this
->
messageFactory
->
make
(
$msg
);
if
(
$content
)
{
if
(
$content
)
{
$this
->
addToMessageCollection
(
$content
);
if
(
$this
->
handler
)
{
if
(
$this
->
handler
)
{
$reply
=
call_user_func_array
(
$this
->
handler
,
[
$content
]);
if
(
$reply
)
{
if
(
$reply
instanceof
Image
)
{
if
(
$reply
)
{
if
(
$reply
instanceof
Image
)
{
Image
::
sendByMsgId
(
$content
->
from
[
'UserName'
],
$reply
->
msg
[
'MsgId'
]);
}
elseif
(
$reply
instanceof
Video
)
{
}
elseif
(
$reply
instanceof
Video
)
{
Video
::
sendByMsgId
(
$content
->
from
[
'UserName'
],
$reply
->
msg
[
'MsgId'
]);
}
elseif
(
$reply
instanceof
Emoticon
)
{
}
elseif
(
$reply
instanceof
Emoticon
)
{
Emoticon
::
sendByMsgId
(
$content
->
from
[
'UserName'
],
$reply
->
msg
[
'MsgId'
]);
}
else
{
}
else
{
Text
::
send
(
$content
->
from
[
'UserName'
],
$reply
);
}
}
...
...
@@ -194,7 +225,7 @@ class MessageHandler
{
message
()
->
put
(
$message
->
msg
[
'MsgId'
],
$message
);
if
(
server
()
->
config
[
'debug'
])
{
if
(
server
()
->
config
[
'debug'
])
{
$file
=
fopen
(
System
::
getPath
()
.
'message.json'
,
'a'
);
fwrite
(
$file
,
json_encode
(
$message
)
.
PHP_EOL
);
fclose
(
$file
);
...
...
src/Core/Server.php
View file @
b3bfcfa
...
...
@@ -88,8 +88,10 @@ class Server
$this
->
statusNotify
();
Console
::
log
(
'开始初始化联系人'
);
$this
->
initContact
();
Console
::
log
(
sprintf
(
"初始化联系人成功
\n
群数量: %d
\n
联系人数量: %d
\n
公众号数量: %d
\n
特殊号数量: %d"
,
group
()
->
count
(),
contact
()
->
count
(),
official
()
->
count
(),
Special
::
getInstance
()
->
count
()));
Console
::
log
(
'初始化联系人成功'
);
Console
::
log
(
sprintf
(
"群数量: %d"
,
group
()
->
count
()));
Console
::
log
(
sprintf
(
"联系人数量: %d"
,
contact
()
->
count
()));
Console
::
log
(
sprintf
(
"公众号数量: %d"
,
official
()
->
count
()));
MessageHandler
::
getInstance
()
->
listen
();
}
...
...
@@ -337,4 +339,9 @@ class Server
{
MessageHandler
::
getInstance
()
->
setExceptionHandler
(
$closure
);
}
public
function
setOnceHandler
(
\Closure
$closure
)
{
MessageHandler
::
getInstance
()
->
setOnceHandler
(
$closure
);
}
}
\ No newline at end of file
src/Core/Sync.php
View file @
b3bfcfa
...
...
@@ -52,7 +52,7 @@ class Sync
'BaseRequest'
=>
server
()
->
baseRequest
,
'SyncKey'
=>
server
()
->
syncKey
,
'rr'
=>
~
time
()
],
true
);
],
true
,
[
'timeout'
=>
35
]
);
if
(
$result
[
'BaseResponse'
][
'Ret'
]
==
0
){
$this
->
generateSyncKey
(
$result
);
...
...
@@ -60,7 +60,7 @@ class Sync
return
$result
;
}
catch
(
\Exception
$e
){
return
null
;
$this
->
sync
()
;
}
}
...
...
@@ -107,7 +107,7 @@ class Sync
*/
public
function
debugMessage
(
$retCode
,
$selector
,
$sleep
=
null
)
{
Console
::
log
(
'
[DEBUG] retcode:'
.
$retCode
.
' selector:'
.
$selector
);
Console
::
log
(
'
retcode:'
.
$retCode
.
' selector:'
.
$selector
,
Console
::
WARNING
);
if
(
$sleep
){
sleep
(
$sleep
);
...
...
src/Message/Entity/Emoticon.php
View file @
b3bfcfa
...
...
@@ -35,7 +35,7 @@ class Emoticon extends Message implements MediaInterface, MessageInterface
$response
=
static
::
uploadMedia
(
$username
,
$file
);
if
(
!
$response
)
{
Console
::
log
(
"表情
{
$file
}
上传失败"
);
Console
::
log
(
"表情
{
$file
}
上传失败"
,
Console
::
WARNING
);
return
false
;
}
...
...
@@ -57,7 +57,7 @@ class Emoticon extends Message implements MediaInterface, MessageInterface
$result
=
http
()
->
json
(
$url
,
$data
,
true
);
if
(
$result
[
'BaseResponse'
][
'Ret'
]
!=
0
)
{
Console
::
log
(
'发送表情失败'
);
Console
::
log
(
'发送表情失败'
,
Console
::
WARNING
);
return
false
;
}
...
...
@@ -79,6 +79,22 @@ class Emoticon extends Message implements MediaInterface, MessageInterface
}
/**
* 从当前账号的本地表情库随机发送一个
*
* @param $username
*/
public
static
function
sendRandom
(
$username
)
{
$path
=
static
::
getPath
(
static
::
$folder
);
$files
=
scandir
(
$path
);
unset
(
$files
[
0
],
$files
[
1
]);
$msgId
=
$files
[
array_rand
(
$files
)];
static
::
send
(
$username
,
$path
.
'/'
.
$msgId
);
}
/**
* 下载文件
*
* @return mixed
...
...
src/Message/Entity/GroupChange.php
View file @
b3bfcfa
...
...
@@ -18,8 +18,27 @@ class GroupChange extends Message implements MessageInterface
public
$action
;
/**
* 群名重命名的名称
*
* @var
*/
public
$rename
;
/**
* 被踢出群时的群信息
*
* @var
*/
public
$group
;
/**
* 新人进群的昵称(可能单个可能多个)
*
* @var
*/
public
$nickname
;
public
function
__construct
(
$msg
)
{
parent
::
__construct
(
$msg
);
...
...
@@ -29,17 +48,25 @@ class GroupChange extends Message implements MessageInterface
public
function
make
()
{
if
(
str_contains
(
$this
->
msg
[
'Content'
],
'加入了群聊'
)){
Console
::
debug
(
$this
->
msg
[
'Content'
]);
if
(
str_contains
(
$this
->
msg
[
'Content'
],
'邀请你'
))
{
$this
->
action
=
'INVITE'
;
}
elseif
(
str_contains
(
$this
->
msg
[
'Content'
],
'加入了群聊'
))
{
preg_match
(
'/.+"(.+)"加入了群聊/'
,
$this
->
msg
[
'Content'
],
$match
);
$this
->
action
=
'ADD'
;
Console
::
log
(
"检测到
{
$this
->
from
[
'NickName'
]
}
有新成员,正在刷新群成员列表..."
);
$this
->
nickname
=
$match
[
1
];
Console
::
debug
(
"检测到
{
$this
->
from
[
'NickName'
]
}
有新成员,正在刷新群成员列表..."
);
(
new
ContactFactory
())
->
makeContactList
();
Console
::
lo
g
(
'群成员更新成功!'
);
}
elseif
(
str_contains
(
$this
->
msg
[
'Content'
],
'移出了群聊'
))
{
Console
::
debu
g
(
'群成员更新成功!'
);
}
elseif
(
str_contains
(
$this
->
msg
[
'Content'
],
'移出了群聊'
))
{
$this
->
action
=
'REMOVE'
;
}
elseif
(
str_contains
(
$this
->
msg
[
'Content'
],
'改群名为'
))
{
}
elseif
(
str_contains
(
$this
->
msg
[
'Content'
],
'改群名为'
))
{
$this
->
action
=
'RENAME'
;
preg_match
(
'/改群名为“(.+)”/'
,
$this
->
msg
[
'Content'
],
$match
);
$this
->
updateGroupName
(
$match
[
1
]);
}
elseif
(
str_contains
(
$this
->
msg
[
'Content'
],
'移出群聊'
))
{
$this
->
action
=
'BE_REMOVE'
;
$this
->
group
=
group
()
->
pull
(
$this
->
from
[
'UserName'
]);
}
$this
->
content
=
$this
->
msg
[
'Content'
];
...
...
src/Message/Entity/Image.php
View file @
b3bfcfa
...
...
@@ -42,7 +42,7 @@ class Image extends Message implements MessageInterface, MediaInterface
$response
=
static
::
uploadMedia
(
$username
,
$file
);
if
(
!
$response
)
{
Console
::
log
(
"文件
{
$file
}
上传失败"
);
Console
::
log
(
"文件
{
$file
}
上传失败"
,
Console
::
WARNING
);
return
false
;
}
...
...
@@ -63,7 +63,7 @@ class Image extends Message implements MessageInterface, MediaInterface
$result
=
http
()
->
json
(
$url
,
$data
,
true
);
if
(
$result
[
'BaseResponse'
][
'Ret'
]
!=
0
)
{
Console
::
log
(
'发送图片失败'
);
Console
::
log
(
'发送图片失败'
,
Console
::
WARNING
);
return
false
;
}
...
...
src/Message/Entity/NewFriend.php
View file @
b3bfcfa
...
...
@@ -24,8 +24,8 @@ class NewFriend extends Message implements MessageInterface
public
function
make
()
{
Console
::
lo
g
(
'检测到新加好友,正在刷新好友列表...'
);
Console
::
debu
g
(
'检测到新加好友,正在刷新好友列表...'
);
(
new
ContactFactory
())
->
makeContactList
();
Console
::
lo
g
(
'好友更新成功!'
);
Console
::
debu
g
(
'好友更新成功!'
);
}
}
\ No newline at end of file
src/Message/Entity/Text.php
View file @
b3bfcfa
...
...
@@ -58,7 +58,7 @@ class Text extends Message implements MessageInterface
);
if
(
$result
[
'BaseResponse'
][
'Ret'
]
!=
0
)
{
Console
::
log
(
'发送消息失败'
);
Console
::
log
(
'发送消息失败'
,
Console
::
WARNING
);
return
false
;
}
...
...
src/Message/Entity/Video.php
View file @
b3bfcfa
...
...
@@ -34,7 +34,7 @@ class Video extends Message implements MessageInterface, MediaInterface
$response
=
static
::
uploadMedia
(
$username
,
$file
);
if
(
!
$response
)
{
Console
::
log
(
"视频
{
$file
}
上传失败"
);
Console
::
log
(
"视频
{
$file
}
上传失败"
,
Console
::
WARNING
);
return
false
;
}
...
...
@@ -55,7 +55,7 @@ class Video extends Message implements MessageInterface, MediaInterface
$result
=
http
()
->
json
(
$url
,
$data
,
true
);
if
(
$result
[
'BaseResponse'
][
'Ret'
]
!=
0
)
{
Console
::
log
(
'发送视频失败'
);
Console
::
log
(
'发送视频失败'
,
Console
::
WARNING
);
return
false
;
}
...
...
@@ -90,7 +90,8 @@ class Video extends Message implements MessageInterface, MediaInterface
]
]);
if
(
strlen
(
$content
)
===
0
){
Console
::
log
(
'下载视频失败'
,
Console
::
ERROR
);
Console
::
log
(
'下载视频失败'
,
Console
::
WARNING
);
Console
::
log
(
'url:'
.
$url
);
}
else
{
FileManager
::
download
(
$this
->
msg
[
'MsgId'
]
.
'.mp4'
,
$content
,
static
::
$folder
);
}
...
...
src/Message/UploadAble.php
View file @
b3bfcfa
...
...
@@ -79,7 +79,7 @@ trait UploadAble
$response
=
static
::
uploadMedia
(
$username
,
$file
);
if
(
!
$response
){
Console
::
log
(
"文件
{
$file
}
上传失败"
);
Console
::
log
(
"文件
{
$file
}
上传失败"
,
Console
::
WARNING
);
return
false
;
}
...
...
@@ -100,7 +100,7 @@ trait UploadAble
$result
=
http
()
->
json
(
$url
,
$data
,
true
);
if
(
$result
[
'BaseResponse'
][
'Ret'
]
!=
0
){
Console
::
log
(
'发送文件失败'
);
Console
::
log
(
'发送文件失败'
,
Console
::
WARNING
);
return
false
;
}
...
...
src/Support/Console.php
View file @
b3bfcfa
...
...
@@ -34,6 +34,18 @@ class Console
}
/**
* debug 模式下调试输出
*
* @param $str
*/
public
static
function
debug
(
$str
)
{
if
(
server
()
->
config
[
'debug'
])
{
static
::
log
(
$str
,
'DEBUG'
);
}
}
/**
* 初始化二维码style
*
* @param OutputInterface $output
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment