├── .gitattributes
├── .gitignore
├── Action.php
├── Addons
├── DailySentence
│ └── Addon.php
├── DrivingTest
│ └── Addon.php
├── IdCard
│ └── Addon.php
├── IpTaoBao
│ └── Addon.php
├── Moral
│ └── Addon.php
└── Phone
│ └── Addon.php
├── Images
└── UserHeadDefault.jpg
├── Page
├── Addons.php
├── Config.php
├── CustomReply.php
├── Menus.php
└── Users.php
├── Plugin.php
├── README.md
└── Widget
├── Addons.php
├── Config.php
├── CustomReply.php
├── Menus.php
├── Users.php
├── Utils.php
└── WeChat.php
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 |
--------------------------------------------------------------------------------
/Action.php:
--------------------------------------------------------------------------------
1 | db = Typecho_Db::get();
22 | /** 初始化常用组件 */
23 | $this->options = $this->widget('Widget_Options');
24 | $this->user = $this->widget('Widget_User');
25 | }
26 | public function execute() {}
27 |
28 | public function valid() {
29 | $echoStr = $this->request->get('echostr');
30 | if($this->checkSignature($this->options->WCH_token)){
31 | echo $echoStr;
32 | exit;
33 | }
34 | }
35 |
36 | private function checkSignature($token) {
37 | $signature = $this->request->get('signature');
38 | $timestamp = $this->request->get('timestamp');
39 | $nonce = $this->request->get('nonce');
40 |
41 | $tmpArr = array($token, $timestamp, $nonce);
42 | sort($tmpArr, SORT_STRING);
43 | $tmpStr = implode($tmpArr);
44 | $tmpStr = sha1($tmpStr);
45 |
46 | if($tmpStr == $signature){
47 | return true;
48 | }else{
49 | return false;
50 | }
51 | }
52 |
53 | /**
54 | * 数据
55 | *
56 | */
57 | public function postAction(){
58 | Typecho_Widget::widget('WeChatHelper_Widget_WeChat')->action();
59 | /*
60 | $dir = __TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__ . '/WeChatHelper';
61 | $myfile = $dir.'/wechatDebug.txt';
62 | //echo $myfile;
63 | $file_pointer = @fopen($myfile,"a");
64 | @fwrite($file_pointer, $this->get_http_raw());
65 | @fclose($file_pointer);
66 | */
67 | }
68 |
69 | public function action(){
70 | if($this->request->is('valid')){
71 | if($this->request->isGet()){
72 | $this->valid();
73 | }else if($this->request->isPost()){
74 | $this->postAction();
75 | }
76 | }else if($this->request->is('config')){ //插件设置业务
77 | Typecho_Widget::widget('WeChatHelper_Widget_Config')->action();
78 | }else if($this->request->is('customreply')){ //自定义回复业务
79 | Typecho_Widget::widget('WeChatHelper_Widget_CustomReply')->action();
80 | }else if($this->request->is('users')){ //用户业务
81 | Typecho_Widget::widget('WeChatHelper_Widget_Users')->action();
82 | }else if($this->request->is('menus')){ //菜单业务
83 | Typecho_Widget::widget('WeChatHelper_Widget_Menus')->action();
84 | }
85 | /*
86 | if($this->request->isGet()){
87 | $this->on($this->request->is('valid'))->valid();
88 | if($this->request->is('users')){ //用户业务
89 | Typecho_Widget::widget('WeChatHelper_Widget_Users')->action();
90 | }
91 | }
92 | if($this->request->isPost()){
93 | $this->on($this->request->is('valid'))->postAction();
94 | if($this->request->is('config')){ //插件设置业务
95 | Typecho_Widget::widget('WeChatHelper_Widget_Config')->action();
96 | }else if($this->request->is('customreply')){ //自定义回复业务
97 | Typecho_Widget::widget('WeChatHelper_Widget_CustomReply')->action();
98 | }else if($this->request->is('users')){ //用户业务
99 | Typecho_Widget::widget('WeChatHelper_Widget_Users')->action();
100 | }else if($this->request->is('menus')){ //菜单业务
101 | Typecho_Widget::widget('WeChatHelper_Widget_Menus')->action();
102 | }
103 | }
104 | */
105 | }
106 | }
107 | ?>
--------------------------------------------------------------------------------
/Addons/DailySentence/Addon.php:
--------------------------------------------------------------------------------
1 | result = $result;
19 | $this->postObj = $postObj;
20 | $this->params = $params;
21 | }
22 |
23 | public function execute(){
24 | $client = Typecho_Http_Client::get();
25 | //金山词霸http://open.iciba.com/dsapi/
26 | //词海http://en.dict.cn/api/article/daily
27 | $response = $client->send('http://en.dict.cn/api/article/daily');
28 | $response = json_decode($response);
29 | $text = $response->en.chr(10).chr(10);
30 | $text .= $response->ch;
31 | $this->result->setMsgType(MessageTemplate::TEXT)->setText($text)->send();
32 | }
33 | }
34 | ?>
35 |
--------------------------------------------------------------------------------
/Addons/DrivingTest/Addon.php:
--------------------------------------------------------------------------------
1 | result = $result;
16 |
17 | $this->data = array(
18 | array(
19 | 'title' => '驾校一点通模拟考试',
20 | 'description' => '',
21 | 'picurl' => '',
22 | 'url' => ''
23 | ),
24 | array(
25 | 'title' => '小车考试科目一 车型:C1 C2照',
26 | 'description' => '',
27 | 'picurl' => '',
28 | 'url' => 'http://m.jxedt.com/mnks/indexlx.asp'
29 | ),
30 | array(
31 | 'title' => '货车考试科目一 车型:A2 B2照',
32 | 'description' => '',
33 | 'picurl' => '',
34 | 'url' => 'http://m.jxedt.com/mnks/indexlx.asp?type=b'
35 | ),
36 | array(
37 | 'title' => '客车考试科目一 车型:A1 A3 B1照',
38 | 'description' => '',
39 | 'picurl' => '',
40 | 'url' => 'http://m.jxedt.com/mnks/indexlx.asp?type=a'
41 | ),
42 | array(
43 | 'title' => '安全文明科目四 车型:C1 C2 B2照',
44 | 'description' => '',
45 | 'picurl' => '',
46 | 'url' => 'http://m.jxedt.com/mnks/indexlx.asp?type=s'
47 | )
48 | );
49 | }
50 |
51 | public function execute(){
52 | foreach ($this->data as $row) {
53 | $this->result->addItem($row);
54 | }
55 | $this->result->setMsgType(MessageTemplate::NEWS)->send();
56 | }
57 | }
58 | ?>
59 |
--------------------------------------------------------------------------------
/Addons/IdCard/Addon.php:
--------------------------------------------------------------------------------
1 | result = $result;
21 | $this->postObj = $postObj;
22 | $this->params = $params;
23 |
24 | $this->query = array('app' => 'idcard.get',
25 | 'format' => 'json',
26 | 'appkey' => '10755',
27 | 'sign' => 'ce865fa86edc8cdbfe59b3cc27fe621b',
28 | 'idcard' => '');
29 | }
30 |
31 | public function execute(){
32 | $this->get();
33 | }
34 |
35 | private function get(){
36 | if($this->params){
37 | $this->query['idcard'] = $this->params['param'];
38 | }
39 | $this->result->setMsgType(MessageTemplate::TEXT);
40 | $client = Typecho_Http_Client::get();
41 | $response = $client->setQuery($this->query)->send($this->url);
42 | $response = json_decode($response);
43 |
44 | if($response->success){
45 | $text = '号码:'.$response->result->idcard.chr(10);
46 | $text .= '地区:'.$response->result->att.chr(10);
47 | $text .= '出生:'.$response->result->born.chr(10);
48 | $text .= '性别:'.$response->result->sex;
49 | }else{
50 | $text = $response->msg;
51 | }
52 | $this->result->setText($text)->send();
53 | }
54 | }
55 | ?>
56 |
--------------------------------------------------------------------------------
/Addons/IpTaoBao/Addon.php:
--------------------------------------------------------------------------------
1 | result = $result;
21 | $this->postObj = $postObj;
22 | $this->params = $params;
23 |
24 | $this->query = array('ip' => '');
25 | }
26 |
27 | public function execute(){
28 | if($this->params){
29 | $this->query['ip'] = $this->params['param'];
30 | }
31 | $this->result->setMsgType(MessageTemplate::TEXT);
32 | $client = Typecho_Http_Client::get();
33 | $response = $client->setQuery($this->query)->send($this->url);
34 | $response = json_decode($response);
35 | if(!$response->code){
36 | $text = 'IP:'.$response->data->ip.chr(10);
37 | $text .= '国家:'.$response->data->country.chr(10);
38 | $text .= '地区:'.$response->data->area.chr(10);
39 | $text .= '省份:'.$response->data->region.chr(10);
40 | $text .= '城市:'.$response->data->city.chr(10);
41 | $text .= '服务商:'.$response->data->isp;
42 | }else{
43 | $text = 'IP地址错误,请输入正确地址!';
44 | }
45 | $this->result->setText($text)->send();
46 | }
47 | }
48 | ?>
49 |
--------------------------------------------------------------------------------
/Addons/Moral/Addon.php:
--------------------------------------------------------------------------------
1 | result = $result;
18 | $this->postObj = $postObj;
19 | $this->params = $params;
20 | }
21 |
22 | public function execute(){
23 | $name = str_replace("+", "", $this->params['param']);
24 | $f = mb_substr($name, 0, 1, 'utf-8');
25 | $s = mb_substr($name, 1, 1, 'utf-8');
26 | $w = mb_substr($name, 2, 1, 'utf-8');
27 | $x = mb_substr($name, 3, 1, 'utf-8');
28 | $n = ($this->getUnicodeFromUTF8($f) + $this->getUnicodeFromUTF8($s) + $this->getUnicodeFromUTF8($w) + $this->getUnicodeFromUTF8($x)) % 100;
29 | $addd='';
30 | if(empty($name)) {
31 | $addd="大哥不要玩我啊,名字都没有你想算什么!";
32 | } else if ($n <= 0) {
33 | $addd ="你一定不是人吧?怎么一点人品都没有?!";
34 | } else if($n > 0 && $n <= 5) {
35 | $addd ="算了,跟你没什么人品好谈的...";
36 | } else if($n > 5 && $n <= 10) {
37 | $addd ="是我不好...不应该跟你谈人品问题的...";
38 | } else if($n > 10 && $n <= 15) {
39 | $addd ="杀过人没有?放过火没有?你应该无恶不做吧?";
40 | } else if($n > 15 && $n <= 20) {
41 | $addd ="你貌似应该三岁就偷看隔壁大妈洗澡的吧...";
42 | } else if($n > 20 && $n <= 25) {
43 | $addd ="你的人品之低下实在让人惊讶啊...";
44 | } else if($n > 25 && $n <= 30) {
45 | $addd ="你的人品太差了。你应该有干坏事的嗜好吧?";
46 | } else if($n > 30 && $n <= 35) {
47 | $addd ="你的人品真差!肯定经常做偷鸡摸狗的事...";
48 | } else if($n > 35 && $n <= 40) {
49 | $addd ="你拥有如此差的人品请经常祈求佛祖保佑你吧...";
50 | } else if($n > 40 && $n <= 45) {
51 | $addd ="老实交待..那些论坛上面经常出现的偷拍照是不是你的杰作?";
52 | } else if($n > 45 && $n <= 50) {
53 | $addd ="你随地大小便之类的事没少干吧?";
54 | } else if($n > 50 && $n <= 55) {
55 | $addd ="你的人品太差了..稍不小心就会去干坏事了吧?";
56 | } else if($n > 55 && $n <= 60) {
57 | $addd ="你的人品很差了..要时刻克制住做坏事的冲动哦..";
58 | } else if($n > 60 && $n <= 65) {
59 | $addd ="你的人品比较差了..要好好的约束自己啊..";
60 | } else if($n > 65 && $n <= 70) {
61 | $addd ="你的人品勉勉强强..要自己好自为之..";
62 | } else if($n > 70 && $n <= 75) {
63 | $addd ="有你这样的人品算是不错了..";
64 | } else if($n > 75 && $n <= 80) {
65 | $addd ="你有较好的人品..继续保持..";
66 | } else if($n > 80 && $n <= 85) {
67 | $addd ="你的人品不错..应该一表人才吧?";
68 | } else if($n > 85 && $n <= 90) {
69 | $addd ="你的人品真好..做好事应该是你的爱好吧..";
70 | } else if($n > 90 && $n <= 95) {
71 | $addd ="你的人品太好了..你就是当代活雷锋啊...";
72 | } else if($n > 95 && $n <= 99) {
73 | $addd ="你是世人的榜样!";
74 | } else if($n > 100 && $n < 105) {
75 | $addd ="天啦!你不是人!你是神!!!";
76 | }else if($n > 105 && $n < 999) {
77 | $addd="你的人品已经过 100 人品计算器已经甘愿认输,3秒后人品计算器将自杀啊";
78 | } else if($n > 999) {
79 | $addd ="你的人品竟然负溢出了...我对你无语..";
80 | }
81 | $this->result->setText($name."的人品分数为:" . $n . "\n". $addd)->setMsgType(MessageTemplate::TEXT)->send();
82 | }
83 |
84 | function getUnicodeFromUTF8($word) {
85 | if (is_array( $word))
86 | $arr = $word;
87 | else
88 | $arr = str_split($word);
89 | $bin_str = '';
90 | foreach ($arr as $value)
91 | $bin_str .= decbin(ord($value));
92 | $bin_str = preg_replace('/^.{4}(.{4}).{2}(.{6}).{2}(.{6})$/','$1$2$3', $bin_str);
93 | return bindec($bin_str);
94 | }
95 | }
96 | ?>
97 |
--------------------------------------------------------------------------------
/Addons/Phone/Addon.php:
--------------------------------------------------------------------------------
1 | result = $result;
21 | $this->postObj = $postObj;
22 | $this->params = $params;
23 |
24 | $this->query = array('app' => 'phone.get',
25 | 'format' => 'json',
26 | 'appkey' => '10755',
27 | 'sign' => 'ce865fa86edc8cdbfe59b3cc27fe621b',
28 | 'phone' => '');
29 | }
30 |
31 | public function execute(){
32 | $this->get();
33 | }
34 |
35 | private function get(){
36 | if($this->params){
37 | $this->query['phone'] = $this->params['param'];
38 | }
39 | $this->result->setMsgType(MessageTemplate::TEXT);
40 | $client = Typecho_Http_Client::get();
41 | $response = $client->setQuery($this->query)->send($this->url);
42 | $response = json_decode($response);
43 |
44 | if($response->success){
45 | $text = '号码:'.$response->result->phone.chr(10);
46 | $text .= '地区:'.$response->result->att.chr(10);
47 | $text .= '区号:'.$response->result->area.chr(10);
48 | $text .= '类型:'.$response->result->ctype;
49 | }else{
50 | $text = $response->msg;
51 | }
52 | $this->result->setText($text)->send();
53 | }
54 | }
55 | ?>
56 |
--------------------------------------------------------------------------------
/Images/UserHeadDefault.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/binjoo/WeChatHelper/b8a127f0651693089358f5af26dfbde9019eefd3/Images/UserHeadDefault.jpg
--------------------------------------------------------------------------------
/Page/Addons.php:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
title);?>
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 |
36 |
37 |
38 | getAddons();?>
39 |
40 | $row) { ?>
41 |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 |
49 |
50 |
51 |
52 | |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
67 |
--------------------------------------------------------------------------------
/Page/Config.php:
--------------------------------------------------------------------------------
1 | type ? $request->type : '1';
7 | ?>
8 |
9 |
10 |
11 |
12 |
title);?>
13 |
14 |
15 |
16 |
17 |
23 |
24 | baseForm()->render(); ?>
25 |
26 | deluxeForm()->render(); ?>
27 |
28 | thirdPartyForm()->render(); ?>
29 |
30 | creditForm()->render(); ?>
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Page/CustomReply.php:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
13 |
14 |
15 |
39 |
40 |
87 |
88 | have()): ?>
89 |
92 |
93 |
94 |
95 |
96 | form()->render(); ?>
97 |
98 |
99 |
100 |
101 |
105 |
106 |
145 |
146 |
--------------------------------------------------------------------------------
/Page/Menus.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
12 |
13 |
75 |
76 | form()->render(); ?>
77 |
78 |
79 |
80 |
81 |
85 |
86 |
103 |
104 |
--------------------------------------------------------------------------------
/Page/Users.php:
--------------------------------------------------------------------------------
1 | siteUrl;
6 | ?>
7 |
8 |
9 |
10 |
title);?>
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 |
58 |
59 |
60 | to($users);?>
61 | have()): ?>
62 | next()): ?>
63 |
64 |  ?>) |
65 | openid) ?> |
66 | nickname) ?> |
67 | sexVal) ?> |
68 | address) ?> |
69 | subscribeFormat) ?> |
70 | credits) ?> |
71 | bindVal) ?> |
72 |
73 |
74 | 更新|详情
75 | |
76 |
77 |
78 |
79 |
80 | |
81 |
82 |
83 |
84 |
85 |
86 |
87 | have()): ?>
88 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
102 |
--------------------------------------------------------------------------------
/Plugin.php:
--------------------------------------------------------------------------------
1 | getAdapterName() || "Mysql" === $db->getAdapterName()){
15 | /**
16 | * 创建关键字表
17 | */
18 | $db->query("CREATE TABLE IF NOT EXISTS " . $db->getPrefix() . 'wch_keywords' . " (
19 | `kid` int(11) NOT NULL AUTO_INCREMENT,
20 | `name` varchar(100) NOT NULL,
21 | `rid` int(11) NOT NULL,
22 | PRIMARY KEY (`kid`)
23 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1");
24 | /**
25 | * 创建自定义回复表
26 | */
27 | $db->query("CREATE TABLE IF NOT EXISTS " . $db->getPrefix() . 'wch_reply' . " (
28 | `rid` int(11) NOT NULL AUTO_INCREMENT,
29 | `keywords` varchar(200) DEFAULT NULL,
30 | `type` varchar(20) DEFAULT 'text',
31 | `command` varchar(20) DEFAULT NULL,
32 | `param` char(1) DEFAULT '0',
33 | `content` text,
34 | `status` char(1) DEFAULT '0',
35 | `created` int(10) DEFAULT '0',
36 | PRIMARY KEY (`rid`)
37 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1");
38 | /**
39 | * 创建用户管理表
40 | */
41 | $db->query("CREATE TABLE IF NOT EXISTS " . $db->getPrefix() . 'wch_users' . " (
42 | `uid` int(11) NOT NULL AUTO_INCREMENT,
43 | `openid` varchar(50) DEFAULT '',
44 | `nickname` varchar(100) DEFAULT '',
45 | `sex` char(1) DEFAULT '',
46 | `language` varchar(50) DEFAULT '',
47 | `city` varchar(50) DEFAULT '',
48 | `province` varchar(50) DEFAULT '',
49 | `country` varchar(50) DEFAULT '',
50 | `headimgurl` varchar(200) DEFAULT '',
51 | `subscribe_time` int(10) DEFAULT '0',
52 | `credits` int(10) NOT NULL DEFAULT '0',
53 | `bind` int(3) DEFAULT '0',
54 | `status` char(1) DEFAULT '1',
55 | `created` int(10) DEFAULT '0',
56 | `synctime` int(10) DEFAULT '0',
57 | PRIMARY KEY (`uid`)
58 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1");
59 | /**
60 | * 创建自定义菜单表
61 | */
62 | $db->query("CREATE TABLE IF NOT EXISTS " . $db->getPrefix() . 'wch_menus' . " (
63 | `mid` int(11) NOT NULL AUTO_INCREMENT,
64 | `level` varchar(10) DEFAULT 'button',
65 | `name` varchar(200) DEFAULT '',
66 | `type` varchar(10) DEFAULT 'view',
67 | `value` varchar(200) DEFAULT '',
68 | `sort` int(3) DEFAULT '0',
69 | `order` int(3) DEFAULT '1',
70 | `parent` int(11) DEFAULT '0',
71 | `created` int(10) DEFAULT '0',
72 | PRIMARY KEY (`mid`)
73 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1");
74 | }else{
75 | throw new Typecho_Plugin_Exception(_t('对不起, 本插件仅支持MySQL数据库。'));
76 | }
77 |
78 | $index = Helper::addMenu('微信助手');
79 | Helper::addAction('WeChat', 'WeChatHelper_Action');
80 | Helper::addPanel($index, 'WeChatHelper/Page/Config.php', '参数设置', '参数设置', 'administrator');
81 | Helper::addPanel($index, 'WeChatHelper/Page/Users.php', '用户管理', '用户管理', 'administrator');
82 | Helper::addPanel($index, 'WeChatHelper/Page/Menus.php', '自定义菜单', '自定义菜单', 'administrator');
83 | Helper::addPanel($index, 'WeChatHelper/Page/CustomReply.php', '自定义回复', '自定义回复', 'administrator');
84 | Helper::addPanel($index, 'WeChatHelper/Page/Addons.php', '插件扩展', '插件扩展', 'administrator');
85 | return('微信助手已经成功激活,请进入设置Token!');
86 | }
87 |
88 | public static function deactivate() {
89 | $db = Typecho_Db::get();
90 | $options = Typecho_Widget::widget('Widget_Options');
91 | if (isset($options->WeChatHelper_dropTable) && $options->WeChatHelper_dropTable) {
92 | if("Pdo_Mysql" === $db->getAdapterName() || "Mysql" === $db->getAdapterName()){
93 | $db->query("drop table ".$db->getPrefix()."wch_keywords, ".$db->getPrefix()."wch_reply, ".$db->getPrefix()."wch_users, ".$db->getPrefix()."wch_menus");
94 | $db->query($db->sql()->delete('table.options')->where('name like ?', "WeChatHelper_%"));
95 | }
96 | }
97 | $index = Helper::removeMenu('微信助手');
98 | Helper::removePanel($index, 'WeChatHelper/Page/Config.php');
99 | Helper::removePanel($index, 'WeChatHelper/Page/Users.php');
100 | Helper::removePanel($index, 'WeChatHelper/Page/Menus.php');
101 | Helper::removePanel($index, 'WeChatHelper/Page/CustomReply.php');
102 | Helper::removePanel($index, 'WeChatHelper/Page/Addons.php');
103 | Helper::removeAction('WeChat');
104 | }
105 |
106 | public static function config(Typecho_Widget_Helper_Form $form) {
107 | }
108 |
109 | public static function personalConfig(Typecho_Widget_Helper_Form $form){}
110 | }
111 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 插件说明 ##
2 |
3 | - 版本: v2.2.1
4 | - 作者: [冰剑](https://github.com/binjoo)
5 | - 主页:
6 |
7 | `此插件涉及数据库操作,有潜在的未知风险,请慎用!`
8 |
9 | ## 插件特点 ##
10 |
11 | - 自定义菜单功能
12 | - 自定义回复功能
13 | - 第三方微信平台
14 | - 插件机制
15 |
16 | ## 使用方法 ##
17 |
18 | 1. 下载插件
19 | 2. 如果安装有老版本,请先卸载老版本,再删除插件文件
20 | 3. 将插件上传到 /usr/plugins/ 这个目录下
21 | 4. 登陆后台,在“控制台”下拉菜单中进入“插件管理”
22 | 5. 启用当前插件
23 | 6. 在“微信助手”下拉菜单中进入“参数设置”设置TOKEN相关信息
24 |
25 | ## 更新记录 ##
26 | #### v2.2.1
27 | - 优化参数设置安全提交路径;
28 | - 优化自定义回复安全提交路径;
29 | - 新增IP查询扩展;
30 | - 优化OPTIONS表KEY命名,方便扩展设置;
31 |
32 | #### v2.2.0
33 | - 新增自定义菜单功能;
34 | - 新增用户积分;
35 | - 新增关注奖励积分设置;
36 | - 优化参数设置规则;
37 |
38 | #### v2.1.0
39 | - 新增用户管理;
40 | - 新增插件扩展页面;
41 | - 优化设计插件规则;
42 |
43 | #### v2.0.0
44 | - 新增自定义回复功能;
45 | - 新增第三方微信平台;
46 | - 新增插件机制;
47 |
48 | #### v1.0.1
49 | - 新增 管理员用户绑定
50 | - 新增 管理员用户解除绑定
51 | - 新增 设置项验证码
52 | - 新增 设置项绑定用户
53 |
54 | #### v1.0.1
55 | - 新增 手气不错(命令 "l")
56 | - 新增 自定义订阅欢迎语
57 | - 新增 设置项默认图片
58 | - 新增 设置项返回图文数量
59 | - 新增 设置项访客评论排行榜数量
60 | - 新增 设置项日志截取字数
61 | - 修复 搜索日志BUG
62 |
63 | #### v1.0.0
64 | - 新增 最新日志(命令 "n")
65 | - 新增 随机日志(命令 "r")
66 | - 新增 搜索日志(命令 "s 关键词")
67 | - 新增 访客评论排行榜(命令 "f")
68 |
--------------------------------------------------------------------------------
/Widget/Addons.php:
--------------------------------------------------------------------------------
1 | parseInfo($file);
25 | if ($info['name'] != '' && $info['package'] != '') {
26 | $result[$file] = $info;
27 | }
28 | }
29 | return $result;
30 | }
31 |
32 | public function parseInfo($file){
33 | $tokens = token_get_all(file_get_contents($file));
34 | $isDoc = false;
35 |
36 | $info = array(
37 | 'name' => '',
38 | 'author' => '',
39 | 'link' => '',
40 | 'package' => '',
41 | 'version' => '',
42 | 'description' => '',
43 | 'param' => ''
44 | );
45 |
46 | foreach ($tokens as $token) {
47 | if (is_array($token) && T_DOC_COMMENT == $token[0]) {
48 | /** 分行读取 */
49 | $lines = preg_split("(\r|\n)", $token[1]);
50 | foreach ($lines as $line) {
51 | $line = trim($line);
52 | if (!empty($line) && '*' == $line[0]) {
53 | $line = trim(substr($line, 1));
54 |
55 | if (!empty($line) && '@' == $line[0]) {
56 | $line = trim(substr($line, 1));
57 | $args = explode(' ', $line);
58 | $key = array_shift($args);
59 | if (isset($key)) {
60 | $info[$key] = trim(implode(' ', $args));
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | return $info;
68 | }
69 |
70 | public function action() {
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Widget/Config.php:
--------------------------------------------------------------------------------
1 | security->getIndex('action/WeChat?config&do=base'), Typecho_Widget_Helper_Form::POST_METHOD);
21 |
22 | $token = new Typecho_Widget_Helper_Form_Element_Text('token', NULL, NULL,
23 | _t('TOKEN'), _t('TOKEN内容自定义,需要与开发模式服务器配置中填写一致,推荐使用GUID。'));
24 | $token->value(isset($this->options->WCH_token) ? $this->options->WCH_token : '');
25 | $form->addInput($token);
26 |
27 | $welcome = new Typecho_Widget_Helper_Form_Element_Textarea('welcome', NULL, NULL, _t('欢迎提示语'), _t('用户在关注公众号时,会发送欢迎的提示消息。'));
28 | $welcome->value(isset($this->options->WCH_welcome) ? $this->options->WCH_welcome : Utils::getDefaultMessage('welcome'));
29 | $form->addInput($welcome);
30 |
31 | $notfound = new Typecho_Widget_Helper_Form_Element_Textarea('notfound', NULL, NULL, _t('找不到提示语'), _t('没开启第三方平台搜索功能时,会发送找不到的提示消息。'));
32 | $notfound->value(isset($this->options->WCH_notfound) ? $this->options->WCH_notfound : Utils::getDefaultMessage('notfound'));
33 | $form->addInput($notfound);
34 |
35 | $dropTable = new Typecho_Widget_Helper_Form_Element_Radio('dropTable',
36 | array('1' => _t('开启'), '0' => _t('关闭')),
37 | NULL, _t('数据删除'), _t('开启后,禁用插件会删除插件设置数据和数据表。'));
38 | $dropTable->value(isset($this->options->WCH_dropTable) ? $this->options->WCH_dropTable : '0');
39 | $form->addInput($dropTable);
40 |
41 | $submit = new Typecho_Widget_Helper_Form_Element_Submit(NULL, NULL, _t('保存设置'));
42 | $submit->input->setAttribute('class', 'btn primary');
43 | $form->addItem($submit);
44 |
45 | return $form;
46 | }
47 |
48 | /**
49 | * 高级功能
50 | */
51 | public function deluxeForm() {
52 | $form = new Typecho_Widget_Helper_Form($this->security->getIndex('action/WeChat?config&do=deluxe'), Typecho_Widget_Helper_Form::POST_METHOD);
53 |
54 | $appid = new Typecho_Widget_Helper_Form_Element_Text('appid', NULL, NULL,
55 | _t('APP ID'), _t('TOKEN内容自定义,需要与开发模式服务器配置中填写一致,推荐使用GUID。'));
56 | $appid->value(isset($this->options->WCH_appid) ? $this->options->WCH_appid : '');
57 | $form->addInput($appid);
58 |
59 | $appsecret = new Typecho_Widget_Helper_Form_Element_Text('appsecret', NULL, NULL,
60 | _t('APP Secret'), _t('TOKEN内容自定义,需要与开发模式服务器配置中填写一致,推荐使用GUID。'));
61 | $appsecret->value(isset($this->options->WCH_appsecret) ? $this->options->WCH_appsecret : '');
62 | $form->addInput($appsecret);
63 |
64 | $access_token = new Typecho_Widget_Helper_Form_Element_Hidden('access_token', NULL, NULL);
65 | $access_token->value(isset($this->options->WCH_access_token) ? $this->options->WCH_access_token : '');
66 | $form->addInput($access_token);
67 |
68 | $expires_in = new Typecho_Widget_Helper_Form_Element_Hidden('expires_in', NULL, NULL);
69 | $expires_in->value(isset($this->options->WCH_expires_in) ? $this->options->WCH_expires_in : '0');
70 | $form->addInput($expires_in);
71 |
72 | $submit = new Typecho_Widget_Helper_Form_Element_Submit(NULL, NULL, _t('保存设置'));
73 | $submit->input->setAttribute('class', 'btn primary');
74 | $form->addItem($submit);
75 |
76 | return $form;
77 | }
78 |
79 | /**
80 | * 第三方
81 | */
82 | public function thirdPartyForm() {
83 | $form = new Typecho_Widget_Helper_Form($this->security->getIndex('action/WeChat?config&do=thirdParty'), Typecho_Widget_Helper_Form::POST_METHOD);
84 |
85 | $thirdPartyUrl = new Typecho_Widget_Helper_Form_Element_Text('thirdPartyUrl', NULL, $this->options->WCH_thirdPartyUrl,
86 | _t('第三方平台链接'), _t('推荐平台:小i机器人'));
87 | $form->addInput($thirdPartyUrl);
88 |
89 | $thirdPartyToken = new Typecho_Widget_Helper_Form_Element_Text('thirdPartyToken', NULL, $this->options->WCH_thirdPartyToken, _t('第三方平台Token'), NULL);
90 | $form->addInput($thirdPartyToken);
91 |
92 | $thirdPartySearch= new Typecho_Widget_Helper_Form_Element_Radio('thirdPartySearch',
93 | array('1' => _t('开启'), '0' => _t('关闭')),
94 | NULL, _t('第三方平台搜索'),
95 | _t('所有在系统中找不到的关键字是否提交给第三方平台处理。'));
96 | $thirdPartySearch->value(isset($this->options->WCH_thirdPartySearch) ? $this->options->WCH_thirdPartySearch : '0');
97 | $form->addInput($thirdPartySearch);
98 |
99 | $submit = new Typecho_Widget_Helper_Form_Element_Submit(NULL, NULL, _t('保存设置'));
100 | $submit->input->setAttribute('class', 'btn primary');
101 | $form->addItem($submit);
102 |
103 | return $form;
104 | }
105 |
106 | /**
107 | * 积分设置
108 | */
109 | public function creditForm() {
110 | $form = new Typecho_Widget_Helper_Form($this->security->getIndex('action/WeChat?config&do=credit'), Typecho_Widget_Helper_Form::POST_METHOD);
111 |
112 | $subscribe_credit = new Typecho_Widget_Helper_Form_Element_Text('subscribe_credit', NULL, NULL,
113 | _t('订阅积分'), _t('订阅后,初始赠送积分。'));
114 | $subscribe_credit->value(isset($this->options->WCH_subscribe_credit) ? $this->options->WCH_subscribe_credit : '0');
115 | $form->addInput($subscribe_credit);
116 |
117 | $submit = new Typecho_Widget_Helper_Form_Element_Submit(NULL, NULL, _t('保存设置'));
118 | $submit->input->setAttribute('class', 'btn primary');
119 | $form->addItem($submit);
120 |
121 | return $form;
122 | }
123 |
124 | public function updateConfig(){
125 | $baseForm = array('token', 'welcome', 'notfound', 'dropTable');
126 | $deluxeForm = array('appid', 'appsecret', 'access_token', 'expires_in');
127 | $thirdPartyForm = array('thirdPartyUrl', 'thirdPartyToken', 'thirdPartySearch');
128 | $creditForm = array('subscribe_credit');
129 | $do = $this->request->get('do').'Form';
130 |
131 | $settings = $this->request->from(${$do}); //动态传递表单参数
132 | foreach ($settings as $key => $value) {
133 | //if(!is_null($settings[$key])){ //判断参数是否为NULL
134 | $row['name'] = 'WCH_'.$key;
135 | $row['value'] = $value;
136 | if($this->db->fetchRow($this->select()->where('name = ?', $row['name'])->limit(1))){
137 | $this->update($row, $this->db->sql()->where('name = ?', $row['name']));
138 | }else{
139 | $this->insert($row);
140 | }
141 | //}
142 | }
143 | /** 提示信息 */
144 | $this->widget('Widget_Notice')->set(_t('设置已经保存'), 'success');
145 |
146 | /** 转向原页 */
147 | $this->response->goBack();
148 | }
149 |
150 | public function action() {
151 | $this->on($this->request->is('do'))->updateConfig();
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/Widget/CustomReply.php:
--------------------------------------------------------------------------------
1 | siteUrl = Helper::options()->siteUrl;
16 | }
17 | public function getCurrentPage(){
18 | return $this->_currentPage ? $this->_currentPage : 1;
19 | }
20 | public function select() {
21 | return $this->db->select()->from('table.wch_reply');
22 | }
23 | public function insert(array $options) {
24 | return $this->db->query($this->db->insert('table.wch_reply')->rows($options));
25 | }
26 | public function update(array $options, Typecho_Db_Query $condition){
27 | return $this->db->query($condition->update('table.wch_reply')->rows($options));
28 | }
29 | public function delete(Typecho_Db_Query $condition){
30 | return $this->db->query($condition->delete('table.wch_reply'));
31 | }
32 | public function size(Typecho_Db_Query $condition){
33 | return $this->db->fetchObject($condition->select(array('COUNT(table.wch_reply.rid)' => 'num'))->from('table.wch_reply'))->num;
34 | }
35 | public function execute(){
36 | $this->parameter->setDefault('pageSize=10');
37 | $this->_currentPage = $this->request->get('page', 1);
38 |
39 | /** 构建基础查询 */
40 | $select = $this->db->select()->from('table.wch_reply');
41 |
42 | /** 过滤分类 */
43 | if (NULL != ($keywords = $this->request->keywords)) {
44 | $rids = $this->db->fetchAll($this->db->select('distinct rid')->from('table.wch_keywords')->where('name like ?', '%' . $keywords . '%'));
45 | foreach ($rids as $rid) {
46 | $select->orWhere('rid = ?', $rid['rid']);
47 | }
48 | }
49 |
50 | /** 过滤类别 */
51 | if (NULL != ($type = $this->request->type)) {
52 | $select->where('type = ?', $type);
53 | }
54 |
55 | /** 给计算数目对象赋值,克隆对象 */
56 | $this->_countSql = clone $select;
57 |
58 | /** 提交查询 */
59 | $select->page($this->_currentPage, $this->parameter->pageSize)->order('table.wch_reply.rid', Typecho_Db::SORT_DESC);
60 | $this->db->fetchAll($select, array($this, 'push'));
61 | }
62 |
63 | /**
64 | * 输出分页
65 | */
66 | public function pageNav() {
67 | $query = $this->request->makeUriByRequest('page={page}');
68 |
69 | /** 使用盒状分页 */
70 | $nav = new Typecho_Widget_Helper_PageNavigator_Box(false === $this->_total ? $this->_total = $this->size($this->_countSql) : $this->_total, $this->_currentPage, $this->parameter->pageSize, $query);
71 | $nav->render('«', '»');
72 | }
73 | /**
74 | * 生成表单
75 | *
76 | * @access public
77 | * @param string $action 表单动作
78 | * @return Typecho_Widget_Helper_Form_Element
79 | */
80 | public function form($action = NULL) {
81 | if (isset($this->request->rid) && 'insert' != $action) {
82 | /** 更新模式 */
83 | $custom = $this->db->fetchRow($this->select()->where('rid = ?', $this->request->rid)->limit(1));
84 |
85 | if (!$custom) {
86 | $this->response->redirect(Helper::url('WeChatHelper/Page/CustomReply.php', $this->options->adminUrl));
87 | }
88 | }
89 |
90 | /** 构建表格 */
91 | $form = new Typecho_Widget_Helper_Form($this->security->getIndex('action/WeChat?customreply'), Typecho_Widget_Helper_Form::POST_METHOD);
92 |
93 | $keywords = new Typecho_Widget_Helper_Form_Element_Text('keywords', NULL, NULL,
94 | _t('关键字'), _t('多个关键字请用英文逗号分开,如:typecho,binjoo,冰剑'));
95 | $form->addInput($keywords);
96 |
97 | $typeOptions = Utils::getMsgType();
98 |
99 | $systemSelect = '';
108 | $typeOptions['system'] = $typeOptions['system'] . ' ' . $systemSelect; //系统消息
109 |
110 | $addonsArray = Typecho_Widget::widget('WeChatHelper_Widget_Addons')->getAddons();
111 | if(count($addonsArray)){
112 | $addonsSelect = '';
121 | $typeOptions['addons'] = $typeOptions['addons'] . ' ' . $addonsSelect;
122 | }else{
123 | unset($typeOptions['addons']);
124 | }
125 |
126 | $type = new Typecho_Widget_Helper_Form_Element_Radio('type', $typeOptions, 'text', '消息类型', NULL);
127 | $form->addInput($type->multiMode());
128 |
129 | $content = new Typecho_Widget_Helper_Form_Element_Textarea('content', NULL, NULL, '回复内容', '
130 | 文本消息:填写需要回复的内容;
131 | 图片消息:填写图片绝对路径即可;
132 | 系统消息:不需要填写任何内容。');
133 | $form->addInput($content);
134 |
135 | $status = new Typecho_Widget_Helper_Form_Element_Radio('status',
136 | array('1' => '激活', '0' => '冻结'),
137 | '1', '激活状态', NULL);
138 | $form->addInput($status);
139 |
140 | $command = new Typecho_Widget_Helper_Form_Element_Hidden('command', NULL, NULL);
141 | $form->addInput($command);
142 |
143 | $param = new Typecho_Widget_Helper_Form_Element_Hidden('param', NULL, NULL);
144 | $form->addInput($param);
145 |
146 | $rid = new Typecho_Widget_Helper_Form_Element_Hidden('rid', NULL, NULL);
147 | $form->addInput($rid);
148 |
149 | $do = new Typecho_Widget_Helper_Form_Element_Hidden('do', NULL, NULL);
150 | $form->addInput($do);
151 |
152 | $submit = new Typecho_Widget_Helper_Form_Element_Submit(NULL, NULL, _t('保存自定义回复'));
153 | $submit->input->setAttribute('class', 'btn primary');
154 | $form->addItem($submit);
155 |
156 | if (isset($this->request->rid) && 'insert' != $action) {
157 | if($custom['type'] == "system"){
158 | $content->input->setAttribute('readonly', true);
159 | }
160 | $keywords->value($custom['keywords']);
161 | $type->value($custom['type']);
162 | $command->value($custom['command']);
163 | $param->value($custom['param']);
164 | $content->value($custom['content']);
165 | $status->value($custom['status']);
166 | $rid->value($custom['rid']);
167 | $submit->value(_t('编辑自定义回复'));
168 | $do->value('update');
169 | $_action = 'update';
170 | } else {
171 | $submit->value(_t('增加自定义回复'));
172 | $do->value('insert');
173 | $_action = 'insert';
174 | }
175 |
176 | if (empty($action)) {
177 | $action = $_action;
178 | }
179 |
180 | /** 给表单增加规则 */
181 | if ('insert' == $action || 'update' == $action) {
182 | $keywords->addRule('required', _t('关键字不能为空'));
183 | $keywords->addRule(array($this, 'keywordsExists'), _t('关键字名称已经存在'));
184 | //$type->addRule(array($this, 'typeExists'), _t('该系统消息类型已经存在'));
185 | $content->addRule('required', _t('回复内容不能为空'));
186 | //$content->addRule(array($this, 'contentExists'), _t('关键字名称已经存在'));
187 | }
188 |
189 | if ('update' == $action) {
190 | $rid->addRule('required', _t('分类主键不存在'));
191 | //$mid->addRule(array($this, 'categoryExists'), _t('分类不存在'));
192 | }
193 |
194 | return $form;
195 | }
196 |
197 | public function insertCustomReply(){
198 | if ($this->form('insert')->validate()) {
199 | $this->response->goBack();
200 | }
201 |
202 | /** 取出数据 */
203 | $customReply = $this->request->from('keywords', 'type', 'command', 'param', 'content', 'status');
204 |
205 | $customReply['created'] = time();
206 |
207 | /** 插入数据 */
208 | $customReply['rid'] = $this->db->query($this->insert($customReply));
209 | $this->insertKeywords($customReply);
210 | $this->push($customReply);
211 |
212 | /** 设置高亮 */
213 | $this->widget('Widget_Notice')->highlight('rid-customreply-'.$customReply['rid']);
214 |
215 | /** 提示信息 */
216 | $this->widget('Widget_Notice')->set(_t('自定义回复 %s 已经被增加', $customReply['keywords']), 'success');
217 |
218 | /** 转向原页 */
219 | $this->response->redirect(Helper::url('WeChatHelper/Page/CustomReply.php', $this->options->adminUrl));
220 | }
221 |
222 | public function updateCustomReply(){
223 | if ($this->form('update')->validate()) {
224 | $this->response->goBack();
225 | }
226 | /** 取出数据 */
227 | $customReply = $this->request->from('keywords', 'type', 'command', 'param', 'content', 'status', 'rid');
228 |
229 | /** 更新数据 */
230 | $this->db->query($this->update($customReply, $this->db->sql()->where('rid = ?', $this->request->filter('int')->rid)));
231 | $this->db->query($this->db->sql()->delete('table.wch_keywords')->where('rid = ?', $customReply['rid']));
232 | $this->insertKeywords($customReply);
233 | $this->push($customReply);
234 |
235 | /** 设置高亮 */
236 | $this->widget('Widget_Notice')->highlight('rid-customreply-'.$customReply['rid']);
237 |
238 | /** 提示信息 */
239 | $this->widget('Widget_Notice')->set(_t('自定义回复 %s 已经被更新', $customReply['keywords']), 'success');
240 |
241 | /** 转向原页 */
242 | $this->response->redirect(Helper::url('WeChatHelper/Page/CustomReply.php&page='.$this->_currentPage, $this->options->adminUrl));
243 | }
244 |
245 | public function deleteCustomReply(){
246 | $customreplys = $this->request->filter('int')->getArray('rid');
247 | $deleteCount = 0;
248 |
249 | if ($customreplys && is_array($customreplys)) {
250 | foreach ($customreplys as $customreply) {
251 | if ($this->delete($this->db->sql()->where('rid = ?', $customreply))) {
252 | $this->db->query($this->db->sql()->delete('table.wch_keywords')->where('rid = ?', $customreply));
253 | $deleteCount ++;
254 | }
255 | }
256 | }
257 |
258 | /** 提示信息 */
259 | $this->widget('Widget_Notice')->set($deleteCount > 0 ? _t('自定义回复已经删除') : _t('没有自定义回复被删除'),
260 | $deleteCount > 0 ? 'success' : 'notice');
261 |
262 | /** 转向原页 */
263 | $this->response->redirect(Helper::url('WeChatHelper/Page/CustomReply.php', $this->options->adminUrl));
264 | }
265 |
266 | public function insertKeywords($customReply){
267 | foreach (explode(",", $customReply['keywords']) as $key => $value) {
268 | if($value){
269 | $keyObj['name'] = $value;
270 | $keyObj['rid'] = $customReply['rid'];
271 | $this->db->query($this->db->insert('table.wch_keywords')->rows($keyObj));
272 | }
273 | }
274 | }
275 |
276 | /**
277 | * 判断关键字是否存在
278 | */
279 | public function keywordsExists($keywords) {
280 | foreach (explode(",", $keywords) as $key => $value) {
281 | if($value){
282 | $select = $this->db->select()->from('table.wch_keywords')->where('name = ?', $value);
283 | if ($this->request->rid) {
284 | $select->where('rid <> ?', $this->request->rid);
285 | }
286 | $result = $this->db->fetchRow($select->limit(1));
287 | if($result){
288 | break;
289 | }else{
290 | continue;
291 | }
292 | }
293 | }
294 | return $result ? false : true;
295 | }
296 |
297 | /**
298 | * 判断消息类型是否存在
299 | */
300 | public function typeExists($type) {
301 | if($this->request->type === 'system'){
302 | $select = $this->db->select(array('COUNT(table.wch_reply.rid)' => 'num'))->from('table.wch_reply')->where('type = ?', 'system')->where('command = ?', $this->request->command);
303 | if(!is_null($this->request->rid)){
304 | $select->where('rid <> ?', $this->request->rid);
305 | }
306 | $result = $this->db->fetchObject($select);
307 | }
308 | return $result->num ? false : true;
309 | }
310 | public function action() {
311 | $this->security->protect();
312 | $this->on($this->request->is('do=insert'))->insertCustomReply();
313 | $this->on($this->request->is('do=update'))->updateCustomReply();
314 | $this->on($this->request->is('do=delete'))->deleteCustomReply();
315 | $this->response->redirect($this->options->adminUrl);
316 | }
317 | }
318 |
--------------------------------------------------------------------------------
/Widget/Menus.php:
--------------------------------------------------------------------------------
1 | siteUrl = Helper::options()->siteUrl;
16 | }
17 |
18 | public function select() {
19 | return $this->db->select()->from('table.wch_menus');
20 | }
21 | public function insert(array $options) {
22 | return $this->db->query($this->db->insert('table.wch_menus')->rows($options));
23 | }
24 | public function update(array $options, Typecho_Db_Query $condition){
25 | return $this->db->query($condition->update('table.wch_menus')->rows($options));
26 | }
27 | public function delete(Typecho_Db_Query $condition){
28 | return $this->db->query($condition->delete('table.wch_menus'));
29 | }
30 | public function size(Typecho_Db_Query $condition){
31 | return $this->db->fetchObject($condition->select(array('COUNT(table.wch_menus.uid)' => 'num'))->from('table.wch_menus'))->num;
32 | }
33 |
34 | public function execute(){
35 | /** 构建基础查询 */
36 | $select = $this->select()->from('table.wch_menus');
37 |
38 | /** 给计算数目对象赋值,克隆对象 */
39 | $this->_countSql = clone $select;
40 |
41 | /** 提交查询 */
42 | $select->order('table.wch_menus.sort', Typecho_Db::SORT_ASC);
43 | $this->db->fetchAll($select, array($this, 'push'));
44 | }
45 |
46 | public function filter(array $value) {
47 | $value['levelVal'] = $value['level'] == 'button' ? '##' : '└──';
48 | $value['tr'] = $value['level'] == 'button' ? 'style="background-color: #F0F0EC"' : '';
49 | return $value;
50 | }
51 |
52 | public function push(array $value) {
53 | $value = $this->filter($value);
54 | return parent::push($value);
55 | }
56 |
57 | /**
58 | * 生成表单
59 | *
60 | * @access public
61 | * @param string $action 表单动作
62 | * @return Typecho_Widget_Helper_Form_Element
63 | */
64 | public function form($action = NULL) {
65 | if (isset($this->request->mid) && 'insert' != $action) {
66 | /** 更新模式 */
67 | $menu = $this->db->fetchRow($this->select()->where('mid = ?', $this->request->mid)->limit(1));
68 |
69 | if (!$menu) {
70 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
71 | }
72 | }
73 | /** 构建表格 */
74 | $form = new Typecho_Widget_Helper_Form($this->security->getIndex('action/WeChat?menus'), Typecho_Widget_Helper_Form::POST_METHOD);
75 |
76 | $select = $this->select()->where('table.wch_menus.parent = ?', '0')->order('table.wch_menus.order', Typecho_Db::SORT_ASC);
77 | $buttonMenus = $this->db->fetchAll($select);
78 |
79 | $parent = '';
88 |
89 | $level = new Typecho_Widget_Helper_Form_Element_Radio('level',
90 | array('button' => _t('一级菜单'), 'sub_button' => _t('二级菜单 '.$parent)),
91 | 'button', _t('消息类型'), NULL);
92 | $form->addInput($level->multiMode());
93 |
94 | $name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, NULL,
95 | _t('标题'), _t('菜单标题,不超过16个字节。'));
96 | $form->addInput($name);
97 |
98 | $type = new Typecho_Widget_Helper_Form_Element_Radio('type', array('click' => _t('Click类型'), 'view' => _t('View类型')), 'click', _t('消息类型'), NULL);
99 | $form->addInput($type);
100 |
101 | $value = new Typecho_Widget_Helper_Form_Element_Text('value', NULL, NULL,
102 | _t('Key & URL值'), _t('Click类型:菜单KEY值,用于消息接口推送,不超过128字节;
View类型:网页链接,用户点击菜单可打开链接,不超过256字节。'));
103 | $form->addInput($value);
104 |
105 | $order = new Typecho_Widget_Helper_Form_Element_Select('order',
106 | array('1' => _t('1'),
107 | '2' => _t('2'),
108 | '3' => _t('3'),
109 | '4' => _t('4'),
110 | '5' => _t('5')), '1', _t('排序'), NULL);
111 | $form->addInput($order);
112 |
113 | $do = new Typecho_Widget_Helper_Form_Element_Hidden('do', NULL, NULL);
114 | $form->addInput($do);
115 |
116 | $mid = new Typecho_Widget_Helper_Form_Element_Hidden('mid', NULL, NULL);
117 | $form->addInput($mid);
118 |
119 | $submit = new Typecho_Widget_Helper_Form_Element_Submit(NULL, NULL, NULL);
120 | $submit->input->setAttribute('class', 'btn primary');
121 | $form->addItem($submit);
122 |
123 | if (isset($this->request->mid) && 'insert' != $action) {
124 | $level->value($menu['level']);
125 | $name->value($menu['name']);
126 | $type->value($menu['type']);
127 | $value->value($menu['value']);
128 | $order->value($menu['order']);
129 | $mid->value($menu['mid']);
130 | $submit->value(_t('编辑菜单'));
131 | $do->value('update');
132 | $_action = 'update';
133 | } else {
134 | $submit->value(_t('增加菜单'));
135 | $do->value('insert');
136 | $_action = 'insert';
137 | }
138 |
139 | if (empty($action)) {
140 | $action = $_action;
141 | }
142 |
143 | /** 给表单增加规则 */
144 | if ('insert' == $action || 'update' == $action) {
145 | $level->addRule(array($this, 'checkLevelNum'), _t('一级标题不能超过3个或同一一级标题下的二级标题不能超过5个。'), 'mid');
146 | $name->addRule('required', _t('标题不能为空'));
147 | $name->addRule(array($this, 'checkMaxLength'), _t('菜单标题最多包含16个字符'), 'type');
148 | $value->addRule(array($this, 'checkKeyOrUrl'), _t('URL格式不正确'), 'type');
149 | $value->addRule(array($this, 'checkKeyOrUrlMaxLength'), _t('View类型最多包含128个字符,Click类型最多包含256个字符。'), 'type');
150 | //$name->addRule('checkMaxLength', _t('菜单标题最多包含5个字符'), 5);
151 | }
152 |
153 | if ('update' == $action) {
154 | $mid->addRule('required', _t('菜单主键不存在'));
155 | //$mid->addRule(array($this, 'categoryExists'), _t('分类不存在'));
156 | }
157 |
158 | return $form;
159 | }
160 |
161 | public function checkMaxLength($name, $type){
162 | $type = $this->request->get($type);
163 | $length = 16;
164 | if(strlen($name) > $length){
165 | return false;
166 | }else{
167 | return true;
168 | }
169 | }
170 |
171 | public function checkKeyOrUrl($value, $type){
172 | $type = $this->request->get($type);
173 | if($type == 'view'){
174 | return Typecho_Validate::url($value);
175 | }else{
176 | return true;
177 | }
178 | }
179 |
180 | public function checkLevelNum($value, $mid){
181 | $mid = $this->request->get($mid);
182 | $select = $this->db->sql()->select(array('COUNT(table.wch_menus.mid)' => 'num'))->from('table.wch_menus')->where('level = ?', $value);
183 | if($value == 'button'){
184 | if($mid){
185 | $select->where('mid <> ?', $mid);
186 | }
187 | $num = $this->db->fetchObject($select)->num;
188 | if($num>=3){
189 | return false;
190 | }else{
191 | return true;
192 | }
193 | }else if($value == 'sub_button'){
194 | $parent = $this->request->get('parent');
195 | if($parent){
196 | $select->where('parent = ?', $parent);
197 | }
198 | if($mid){
199 | $select->where('mid <> ?', $mid);
200 | }
201 | $num = $this->db->fetchObject($select)->num;
202 | if($num>=5){
203 | return false;
204 | }else{
205 | return true;
206 | }
207 | }
208 | }
209 |
210 | public function checkKeyOrUrlMaxLength($value, $type){
211 | $type = $this->request->get($type);
212 | $length = $type == 'click' ? 256 : 128;
213 | if(strlen($value) > $length){
214 | return false;
215 | }else{
216 | return true;
217 | }
218 | }
219 |
220 | public function getParentOrder($menu){
221 | if($menu['level'] == 'sub_button'){
222 | $select = $this->db->sql()->select(array('table.wch_menus.order' => 'order'))->from('table.wch_menus')->where('mid = ?', $menu['parent']);
223 | $order = $this->db->fetchObject($select)->order;
224 | $menu['sort'] = ($order * 10) + $menu['order'];
225 | }else{
226 | $menu['sort'] = $menu['order'] * 10;
227 | $menu['parent'] = '0';
228 | }
229 | return $menu;
230 | }
231 |
232 | /**
233 | * 分类排序
234 | *
235 | * @access public
236 | * @return void
237 | */
238 | public function orderMenu() {
239 | $menus = $this->request->filter('int')->getArray('mid');
240 | $levels = $this->request->getArray('level');
241 | if ($menus) {
242 | $parent = 0;
243 | foreach ($menus as $sort => $mid) {
244 | $param = array('order' => $sort + 1);
245 | if($levels[$sort] == 'button'){
246 | $parent = $mid;
247 | $param['parent'] = '0';
248 | }else{
249 | $param['parent'] = $parent;
250 | }
251 | $this->update($param, $this->db->sql()->where('mid = ?', $mid));
252 | }
253 | }
254 |
255 | if (!$this->request->isAjax()) {
256 | /** 转向原页 */
257 | $this->response->redirect(Typecho_Common::url('manage-categories.php', $this->options->adminUrl));
258 | } else {
259 | $this->response->throwJson(array('success' => 1, 'message' => _t('分类排序已经完成')));
260 | }
261 | }
262 |
263 | public function insertMenu() {
264 | if ($this->form('insert')->validate()) {
265 | $this->response->goBack();
266 | }
267 | /** 取出数据 */
268 | $menu = $this->request->from('level', 'name', 'type', 'value', 'parent', 'order');
269 | $menu = $this->getParentOrder($menu);
270 | $menu['created'] = time();
271 |
272 | /** 插入数据 */
273 | $menu['mid'] = $this->db->query($this->insert($menu));
274 | $this->push($menu);
275 |
276 | $this->widget('Widget_Notice')->highlight('menus-mid-'.$menu['mid']);
277 | $this->widget('Widget_Notice')->set(_t('自定义菜单添加成功'), 'success');
278 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
279 | }
280 |
281 | public function updateMenu() {
282 | if ($this->form('insert')->validate()) {
283 | $this->response->goBack();
284 | }
285 | /** 取出数据 */
286 | $menu = $this->request->from('level', 'name', 'type', 'value', 'parent', 'order', 'mid');
287 | $menu = $this->getParentOrder($menu);
288 |
289 | /** 插入数据 */
290 | $this->db->query($this->update($menu, $this->db->sql()->where('mid = ?', $this->request->filter('int')->mid)));
291 | if($menu['level'] == 'button'){
292 | $this->db->query($this->db->sql()->update('table.wch_menus')->where('parent = ?', $menu['mid'])->expression('sort', ($menu['order'] * 10) . ' + `order` '));
293 | }
294 | $this->push($menu);
295 |
296 | $this->widget('Widget_Notice')->highlight('menus-mid-'.$menu['mid']);
297 | $this->widget('Widget_Notice')->set(_t('自定义菜单修改成功'), 'success');
298 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
299 | }
300 |
301 | public function deleteMenu() {
302 | $menus = $this->request->filter('int')->getArray('mid');
303 | $deleteCount = 0;
304 |
305 | if ($menus && is_array($menus)) {
306 | foreach ($menus as $menu) {
307 | if ($this->delete($this->db->sql()->where('mid = ?', $menu)->orWhere('parent = ?', $menu))) {
308 | $deleteCount ++;
309 | }
310 | }
311 | }
312 |
313 | /** 提示信息 */
314 | $this->widget('Widget_Notice')->set($deleteCount > 0 ? _t('自定义菜单已经删除') : _t('没有自定义菜单被删除'),
315 | $deleteCount > 0 ? 'success' : 'notice');
316 |
317 | /** 转向原页 */
318 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
319 | }
320 |
321 | public function createMenu(){
322 | $accessToken = Utils::getAccessToken();
323 | if(!$accessToken){
324 | $this->widget('Widget_Notice')->set('获取Access Token异常!', 'error');
325 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
326 | }
327 | $create['button'] = array();
328 | $select = $this->select()->where('level = ?', 'button')->order('table.wch_menus.order', Typecho_Db::SORT_ASC);
329 | $buttons = $this->db->fetchAll($select);
330 | if (count($buttons) > 3 || !count($buttons)) {
331 | $this->widget('Widget_Notice')->set(_t('错误:一级菜单没有找到或超过三个.'), 'error');
332 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
333 | }
334 | foreach ($buttons as $row) {
335 | $button = array();
336 | $select = "";
337 | $select = $this->select()->where('level = ?', 'sub_button')->where('parent = ?', $row['mid'])->order('table.wch_menus.order', Typecho_Db::SORT_ASC);
338 | $subButtons = $this->db->fetchAll($select);
339 | if (!count($subButtons)) { //没有二级菜单
340 | $button['type'] = urlencode($row['type']);
341 | $button['name'] = urlencode($row['name']);
342 | $button[$row['type'] == 'view' ? 'url' : 'key'] = urlencode($row['value']);
343 | }else{
344 | $button['name'] = urlencode($row['name']);
345 | $tmp = array();
346 | foreach ($subButtons as $row) {
347 | $subButton = array();
348 | $subButton['type'] = urlencode($row['type']);
349 | $subButton['name'] = urlencode($row['name']);
350 | $subButton[$row['type'] == 'view' ? 'url' : 'key'] = urlencode($row['value']);
351 | array_push($tmp, $subButton);
352 | }
353 | $button['sub_button'] = $tmp;
354 | }
355 | array_push($create['button'], $button);
356 | }
357 |
358 | $json = json_encode($create);
359 |
360 | try {
361 | $client = Typecho_Http_Client::get();
362 | $params = array('access_token' => $accessToken);
363 | $response = $client->setQuery($params)->setData(urldecode($json))->send(Utils::MENU_CREATE_URL);
364 | } catch (Exception $e) {
365 | $this->widget('Widget_Notice')->set(_t('对不起,创建自定义菜单失败,请重试!'), 'error');
366 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
367 | }
368 |
369 | $result = json_decode($response);
370 | if($result->errcode){
371 | $this->widget('Widget_Notice')->set(_t('对不起,创建自定义菜单失败,错误原因:'.$result->errmsg), 'notice');
372 | }else{
373 | $this->widget('Widget_Notice')->set(_t('恭喜您,创建自定义菜单成功!'), 'success');
374 | }
375 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
376 | }
377 |
378 | public function removeMenu(){
379 | $accessToken = Utils::getAccessToken();
380 | if(!$accessToken){
381 | $this->widget('Widget_Notice')->set('获取Access Token异常!', 'error');
382 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
383 | }
384 |
385 | try {
386 | $client = Typecho_Http_Client::get();
387 | $params = array('access_token' => $accessToken);
388 | $response = $client->setQuery($params)->send(Utils::MENU_REMOVE_URL);
389 | } catch (Exception $e) {
390 | $this->widget('Widget_Notice')->set(_t('对不起,删除自定义菜单失败,请重试!'), 'error');
391 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
392 | }
393 |
394 | $result = json_decode($response);
395 | if($result->errcode){
396 | $this->widget('Widget_Notice')->set(_t('对不起,删除自定义菜单失败,错误原因:'.$result->errmsg), 'notice');
397 | }else{
398 | $this->widget('Widget_Notice')->set(_t('恭喜您,删除自定义菜单成功!'), 'success');
399 | }
400 | $this->response->redirect(Helper::url('WeChatHelper/Page/Menus.php', $this->options->adminUrl));
401 | }
402 |
403 | public function action() {
404 | $this->security->protect();
405 | $this->on($this->request->is('do=insert'))->insertMenu();
406 | $this->on($this->request->is('do=update'))->updateMenu();
407 | $this->on($this->request->is('do=delete'))->deleteMenu();
408 | $this->on($this->request->is('do=order'))->orderMenu();
409 | $this->on($this->request->is('do=create'))->createMenu();
410 | $this->on($this->request->is('do=remove'))->removeMenu();
411 | $this->response->redirect($this->options->adminUrl);
412 | }
413 | }
414 |
--------------------------------------------------------------------------------
/Widget/Users.php:
--------------------------------------------------------------------------------
1 | siteUrl = Helper::options()->siteUrl;
16 | }
17 | public function getCurrentPage(){
18 | return $this->_currentPage ? $this->_currentPage : 1;
19 | }
20 | public function select() {
21 | return $this->db->select()->from('table.wch_users');
22 | }
23 | public function insert(array $options) {
24 | return $this->db->query($this->db->insert('table.wch_users')->rows($options));
25 | }
26 | public function update(array $options, Typecho_Db_Query $condition){
27 | return $this->db->query($condition->update('table.wch_users')->rows($options));
28 | }
29 | public function delete(Typecho_Db_Query $condition){
30 | return $this->db->query($condition->delete('table.wch_users'));
31 | }
32 | public function size(Typecho_Db_Query $condition){
33 | return $this->db->fetchObject($condition->select(array('COUNT(table.wch_users.uid)' => 'num'))->from('table.wch_users'))->num;
34 | }
35 |
36 | public function execute(){
37 | $this->parameter->setDefault('pageSize=10');
38 | $this->_currentPage = $this->request->get('page', 1);
39 |
40 | /** 构建基础查询 */
41 | $select = $this->db->select()->from('table.wch_users')->where('table.wch_users.status = ?', '1');
42 |
43 | /** 给计算数目对象赋值,克隆对象 */
44 | $this->_countSql = clone $select;
45 |
46 | /** 提交查询 */
47 | $select->page($this->_currentPage, $this->parameter->pageSize)->order('table.wch_users.uid', Typecho_Db::SORT_DESC);
48 | $this->db->fetchAll($select, array($this, 'push'));
49 | }
50 |
51 | public function filter(array $value) {
52 | $date = new Typecho_Date($value['subscribe_time']);
53 | $value['subscribeFormat'] = $date->format('Y-m-d H:i:s');
54 |
55 | $value['bindVal'] = $value['bind'] ? '是' : '否';
56 |
57 | switch ($value['sex']) {
58 | case '1':
59 | $value['sexVal'] = '男';
60 | break;
61 | case '2':
62 | $value['sexVal'] = '女';
63 | break;
64 | default:
65 | $value['sexVal'] = '不明';
66 | break;
67 | }
68 |
69 | $value['address'] = $value['country'] . ',' . $value['province'] . ',' . $value['city'];
70 | if($value['address'] == ',,'){
71 | $value['address'] = '';
72 | }
73 |
74 | if($value['headimgurl']){
75 | $value['headimgurl0'] = $value['headimgurl'].'0';
76 | $value['headimgurl46'] = $value['headimgurl'].'46';
77 | $value['headimgurl64'] = $value['headimgurl'].'64';
78 | $value['headimgurl96'] = $value['headimgurl'].'96';
79 | $value['headimgurl132'] = $value['headimgurl'].'132';
80 | }else{
81 | $value['headimgurl'] = Helper::options()->pluginUrl .'/WeChatHelper/Images/UserHeadDefault.jpg';
82 | $value['headimgurl0'] = $value['headimgurl'];
83 | $value['headimgurl46'] = $value['headimgurl'];
84 | $value['headimgurl64'] = $value['headimgurl'];
85 | $value['headimgurl96'] = $value['headimgurl'];
86 | $value['headimgurl132'] = $value['headimgurl'];
87 | }
88 |
89 | $date = new Typecho_Date($value['created']);
90 | $value['createdFormat'] = $date->format('Y-m-d H:i:s');
91 | return $value;
92 | }
93 |
94 | public function push(array $value) {
95 | $value = $this->filter($value);
96 | return parent::push($value);
97 | }
98 |
99 | /**
100 | * 输出分页
101 | */
102 | public function pageNav() {
103 | $query = $this->request->makeUriByRequest('page={page}');
104 |
105 | /** 使用盒状分页 */
106 | $nav = new Typecho_Widget_Helper_PageNavigator_Box(false === $this->_total ? $this->_total = $this->size($this->_countSql) : $this->_total, $this->_currentPage, $this->parameter->pageSize, $query);
107 | $nav->render('«', '»');
108 | }
109 |
110 | /**
111 | * 生成表单
112 | *
113 | * @access public
114 | * @param string $action 表单动作
115 | * @return Typecho_Widget_Helper_Form_Element
116 | */
117 | public function form($action = NULL) {
118 | }
119 |
120 | /**
121 | * 关注事件
122 | */
123 | public function subscribe($postObj){
124 | //$user = $this->db->fetchRow($this->select()->where('openid = ?', $postObj->FromUserName)->limit(1));
125 | $accessToken = Utils::getAccessToken();
126 | if (!$this->openIdExists((String) $postObj->FromUserName)) {
127 | if($accessToken){
128 | $result = $this->apiGetUser((String) $postObj->FromUserName, $accessToken);
129 | $result = json_decode($result);
130 | $user = (array) $result;
131 | $user['created'] = time();
132 | unset($user['subscribe']);
133 | }else{
134 | $user = array('openid' => $postObj->FromUserName, 'subscribe_time' => time(), 'created' => time());
135 | }
136 | $user['credits'] = isset($this->options->WCH_subscribe_credit) ? $this->options->WCH_subscribe_credit : '0';
137 | $user['uid'] = $this->insert($user);
138 | }else{
139 | $user['status'] = '1';
140 | $user['uid'] = $this->update($user, $this->db->sql()->where('openid = ?', (String) $postObj->FromUserName));
141 | }
142 | }
143 |
144 | /**
145 | * 取消关注事件
146 | */
147 | public function unsubscribe($postObj){
148 | if ($this->openIdExists((String) $postObj->FromUserName)) {
149 | $user['status'] = '0';
150 | $user['uid'] = $this->update($user, $this->db->sql()->where('openid = ?', (String) $postObj->FromUserName));
151 | }
152 | }
153 |
154 | /**
155 | * 判断OpenId是否存在
156 | */
157 | public function openIdExists($openid){
158 | $select = $this->select()->where('openid = ?', $openid)->limit(1);
159 | return $this->db->fetchRow($select);
160 | }
161 |
162 | /**
163 | * 同步微信用户
164 | */
165 | public function syncUserList(){
166 | $accessToken = Utils::getAccessToken();
167 | if(!$accessToken){
168 | $this->widget('Widget_Notice')->set(_t('对不起,更新微信关注者数据失败,请重试!'), 'error');
169 | $this->response->redirect(Helper::url('WeChatHelper/Page/Users.php&page='.$this->_currentPage, $this->options->adminUrl));
170 | }
171 | $client = Typecho_Http_Client::get();
172 | $params = array('access_token' => $accessToken);
173 | $response = $client->setQuery($params)->send('https://api.weixin.qq.com/cgi-bin/user/get');
174 | $response = json_decode($response);
175 |
176 | foreach ($response->data->openid as $val) {
177 | $user = array();
178 | /*
179 | $user = array();
180 | $client = Typecho_Http_Client::get();
181 | $params['openid'] = $val;
182 | $result = $client->setQuery($params)->send('https://api.weixin.qq.com/cgi-bin/user/info');
183 | $result = json_decode($result);
184 | print_r($result);
185 | $user['openid'] = $result->openid;
186 | $user['nickname'] = $result->nickname;
187 | $user['sex'] = $result->sex;
188 | $user['language'] = $result->language;
189 | $user['city'] = $result->city;
190 | $user['province'] = $result->province;
191 | $user['country'] = $result->country;
192 | $user['headimgurl'] = $result->headimgurl;
193 | $user['subscribe_time'] = $result->subscribe_time;
194 | $user['synctime'] = time();
195 | */
196 | $exists = $this->openIdExists($val);
197 | if($exists){
198 | $user['status'] = '1';
199 | $user['uid'] = $this->update($user, $this->db->sql()->where('openid = ?', $val));
200 | }else{
201 | $user['openid'] = $val;
202 | $user['created'] = time();
203 | $user['uid'] = $this->insert($user);
204 | }
205 | }
206 |
207 | $this->widget('Widget_Notice')->set(_t('恭喜您,同步微信关注者列表成功!'), 'success');
208 | $this->response->redirect(Helper::url('WeChatHelper/Page/Users.php&page='.$this->_currentPage, $this->options->adminUrl));
209 | }
210 |
211 | /**
212 | * 同步微信用户信息
213 | */
214 | public function syncUserInfo(){
215 | $uid = $this->request->get('uid');
216 | $user = $this->db->fetchRow($this->select()->where('uid = ?', $uid)->limit(1));
217 |
218 | $accessToken = Utils::getAccessToken();
219 | $client = Typecho_Http_Client::get();
220 | $params = array('access_token' => $accessToken, 'openid' => $user['openid']);
221 | try {
222 | $result = $client->setQuery($params)->send('https://api.weixin.qq.com/cgi-bin/user/info');
223 | } catch (Exception $e) {
224 | $this->widget('Widget_Notice')->set(_t('对不起,更新微信用户信息失败,请重试!'), 'error');
225 | $this->response->redirect(Helper::url('WeChatHelper/Page/Users.php&page='.$this->_currentPage, $this->options->adminUrl));
226 | }
227 | $result = json_decode($result);
228 |
229 | if($result->subscribe){
230 | $user['status'] = '1';
231 | }else{
232 | $user['status'] = '0';
233 | }
234 | $user['openid'] = $result->openid;
235 | $user['nickname'] = $result->nickname;
236 | $user['sex'] = $result->sex;
237 | $user['language'] = $result->language;
238 | $user['city'] = $result->city;
239 | $user['province'] = $result->province;
240 | $user['country'] = $result->country;
241 | $user['headimgurl'] = $result->headimgurl;
242 | $user['subscribe_time'] = $result->subscribe_time;
243 | $user['synctime'] = time();
244 |
245 | $this->update($user, $this->db->sql()->where('uid = ?', $user['uid']));
246 |
247 | $this->widget('Widget_Notice')->highlight('users-uid-'.$user['uid']);
248 | $this->widget('Widget_Notice')->set(_t('微信用户 OpenID %s 更新成功!', $user['openid']), 'success');
249 | $this->response->redirect(Helper::url('WeChatHelper/Page/Users.php&page='.$this->_currentPage, $this->options->adminUrl));
250 | }
251 |
252 | public function apiGetUser($openid, $accessToken = NULL){
253 | if(!$accessToken){
254 | $accessToken = Utils::getAccessToken();
255 | }
256 | if($accessToken){
257 | $client = Typecho_Http_Client::get();
258 | $params = array('access_token' => $accessToken, 'openid' => $openid);
259 | $result = $client->setQuery($params)->send('https://api.weixin.qq.com/cgi-bin/user/info');
260 | }else{
261 | throw new Typecho_Plugin_Exception(_t('对不起,请求AccessToken出现异常。'));
262 | }
263 | return $result;
264 | }
265 |
266 | public function action() {
267 | $this->security->protect();
268 | $this->on($this->request->is('do=syncList'))->syncUserList();
269 | $this->on($this->request->is('do=syncInfo'))->syncUserInfo();
270 | $this->response->redirect($this->options->adminUrl);
271 | }
272 | }
273 |
--------------------------------------------------------------------------------
/Widget/Utils.php:
--------------------------------------------------------------------------------
1 | '哟,客官,您来啦!'.chr(10).'发送\'h\'让小的给您介绍一下!',
8 | 'notfound' => '对不起,我完全不明白你在说什么!'
9 | );
10 | return $tmp[$msg];
11 | }
12 | public static function getMsgType($type = NULL){
13 | $result = array('text' => '文本消息',
14 | //'image' => '图片消息',
15 | 'system' => '系统消息',
16 | 'addons' => '插件扩展');
17 | if($type){
18 | return $result[$type];
19 | }else{
20 | return $result;
21 | }
22 | }
23 |
24 | public static function getSystemMsg(){
25 | $result = array('sys_random' => '随机日志',
26 | 'sys_recent' => '最新日志',
27 | 'sys_hot_comment' => '热评日志');
28 | return $result;
29 | }
30 |
31 | public static function getAccessToken(){
32 | $db = Typecho_Db::get();
33 | $options = Typecho_Widget::widget('Widget_Options');
34 | if(isset($options->WCH_appid) && isset($options->WCH_appsecret)){
35 | if(isset($options->WCH_access_token) && isset($options->WCH_expires_in) && $options->WCH_expires_in > time()){
36 | return $options->WCH_access_token;
37 | }else{
38 | $client = Typecho_Http_Client::get();
39 | $params = array('grant_type' => 'client_credential',
40 | 'appid' => $options->WCH_appid, 'secret' => $options->WCH_appsecret);
41 | $response = $client->setQuery($params)->send('https://api.weixin.qq.com/cgi-bin/token');
42 | $response = json_decode($response);
43 | if(isset($response->errcode)){
44 | //throw new Typecho_Plugin_Exception(_t('对不起,请求错误。ErrCode:'.$response->errcode.' - ErrMsg:'.$response->errmsg));
45 | return NULL;
46 | }else{
47 | $db->query($db->update('table.options')->rows(array('value' => $response->access_token))->where('name = ?', 'WeChatHelper_access_token'));
48 | $db->query($db->update('table.options')->rows(array('value' => time() + $response->expires_in))->where('name = ?', 'WeChatHelper_expires_in'));
49 | return $response->access_token;
50 | }
51 | }
52 | }else{
53 | //throw new Typecho_Plugin_Exception(_t('对不起, 请先在高级功能中填写正确的APP ID和APP Secret。'));
54 | return NULL;
55 | }
56 | }
57 | }
58 |
59 | class MessageTemplate {
60 | const TEXT = 'text'; //文本
61 | const IMAGE = 'image'; //图片
62 | const VOICE = 'voice'; //语音
63 | const VIDEO = 'video'; //视频
64 | const MUSIC = 'music'; //音乐
65 | const NEWS = 'news'; //图文
66 | const THIRD = 'third'; //第三方
67 | private $toUserName;
68 | private $fromUserName;
69 | /**
70 | * 消息时间
71 | */
72 | private $createTime;
73 | /**
74 | * 消息类型
75 | */
76 | private $msgType;
77 | /**
78 | * 最终输出内容
79 | */
80 | private $result;
81 | /**
82 | * 设置消息内容
83 | */
84 | private $content;
85 | /**
86 | *
87 | */
88 | private $item = array();
89 | private $sendContent;
90 | private $_textTpl;
91 | private $_newsTpl;
92 | private $_itemTpl;
93 |
94 | public function __construct($postObj) {
95 | $this->toUserName = $postObj->ToUserName;
96 | $this->fromUserName = $postObj->FromUserName;
97 | $this->createTime = time();
98 | $this->_textTpl = "%s0";
99 | $this->_newsTpl = "%s%s%s0";
100 | $this->_itemTpl = " ";
101 | }
102 | /**
103 | * 设置直接发送的消息内容,适用于第三方平台
104 | */
105 | public function setSendContent($sendContent){
106 | $this->sendContent = $sendContent;
107 | return $this;
108 | }
109 | /**
110 | * 设置消息类型
111 | */
112 | public function setMsgType($msgType){
113 | $this->msgType = $msgType;
114 | return $this;
115 | }
116 | /**
117 | * 设置文本内容
118 | */
119 | public function setText($content) {
120 | $this->content = $content;
121 | return $this;
122 | }
123 | /**
124 | * 组合发送消息
125 | */
126 | public function addItem($item){
127 | array_push($this->item, $item);
128 | }
129 | public function send(){
130 | switch ($this->msgType) {
131 | case MessageTemplate::TEXT:
132 | $this->result = sprintf($this->_textTpl, $this->fromUserName, $this->toUserName, $this->createTime, $this->content);
133 | break;
134 | case MessageTemplate::THIRD:
135 | $this->result = $this->sendContent;
136 | break;
137 | case MessageTemplate::IMAGE:
138 | $this->result = '图片类型';
139 | break;
140 | case MessageTemplate::NEWS:
141 | foreach ($this->item as $key => $value) {
142 | $this->result .= sprintf($this->_itemTpl, $value['title'], $value['description'], $value['picurl'], $value['url']);
143 | }
144 | $this->result = sprintf($this->_newsTpl, $this->fromUserName, $this->toUserName, $this->createTime, count($this->item), $this->result);
145 | break;
146 | default:
147 | $this->result = 'error';
148 | }
149 | echo $this->result;
150 | }
151 | }
152 | ?>
--------------------------------------------------------------------------------
/Widget/WeChat.php:
--------------------------------------------------------------------------------
1 | postObj->Event == "subscribe"){
27 | $info = Typecho_Widget::widget('WeChatHelper_Widget_Users')->subscribe($this->postObj);
28 | $this->result->setText(isset($this->options->WCH_welcome) ? $this->options->WCH_welcome : '')->setMsgType(MessageTemplate::TEXT)->send();
29 | }else if($this->postObj->Event == "unsubscribe"){
30 | $info = Typecho_Widget::widget('WeChatHelper_Widget_Users')->unsubscribe($this->postObj);
31 | }
32 | }
33 | /**
34 | * 文本消息
35 | */
36 | public function isText(){
37 | $val = $this->postObj->Content;
38 | $params = $this->isParam();
39 | if($params){
40 | $val = $params['cmd'];
41 | }
42 |
43 | $select = $this->db->select()->from('table.wch_reply')->join('table.wch_keywords', 'table.wch_keywords.rid = table.wch_reply.rid', Typecho_Db::LEFT_JOIN)->where('table.wch_keywords.name = ?', $val)->where('table.wch_reply.status = ?', 1)->limit(1);
44 | $custom = $this->db->fetchObject($select);
45 | if(isset($custom->content)){ //正常文本处理
46 | if($custom->type === 'text'){
47 | $this->result->setText($custom->content)->setMsgType(MessageTemplate::TEXT)->send();
48 | }else if($custom->type === 'image'){
49 | $this->result->setText('助手暂时还不支持图片回复!')->setMsgType(MessageTemplate::TEXT)->send();
50 | }else if($custom->type === 'system'){
51 | $this->blogPost($custom->command);
52 | }else if($custom->type === 'addons'){
53 | $this->addonsAction($custom->command, $this->postObj, $params);
54 | }
55 | }else if(isset($this->options->WCH_thirdPartySearch) && $this->options->WCH_thirdPartyUrl && $this->options->WCH_thirdPartyToken && $this->options->WCH_thirdPartySearch) { //第三方处理
56 | $this->thirdParty();
57 | }else{
58 | $this->result->setText(isset($this->options->WCH_notfound) ? $this->options->WCH_notfound : '完全不明白你在说什么!')->setMsgType(MessageTemplate::TEXT)->send();
59 | }
60 | }
61 | /**
62 | * 图片消息
63 | */
64 | public function isImage(){
65 | $this->result->setText('助手暂时还不支持图片消息!')->setMsgType(MessageTemplate::TEXT)->send();
66 | }
67 | /**
68 | * 语音消息
69 | */
70 | public function isVoice(){
71 | $this->result->setText('助手暂时还不支持语音消息!')->setMsgType(MessageTemplate::TEXT)->send();
72 | }
73 | /**
74 | * 视频消息
75 | */
76 | public function isVideo(){
77 | $this->result->setText('助手暂时还不支持视频消息!')->setMsgType(MessageTemplate::TEXT)->send();
78 | }
79 | /**
80 | * 地理位置消息
81 | */
82 | public function isLocation(){
83 | $this->result->setText('助手暂时还不支持地理位置消息!')->setMsgType(MessageTemplate::TEXT)->send();
84 | }
85 | /**
86 | * 链接消息
87 | */
88 | public function isLink(){
89 | $this->result->setText('助手暂时还不支持链接消息!')->setMsgType(MessageTemplate::TEXT)->send();
90 | }
91 |
92 | /**
93 | * 是否带有参数
94 | */
95 | public function isParam(){
96 | $select = $this->db->select()->from('table.wch_reply')->join('table.wch_keywords', 'table.wch_keywords.rid = table.wch_reply.rid', Typecho_Db::LEFT_JOIN)->where('table.wch_reply.type = ?', 'addons')->where('table.wch_reply.status = ?', 1);
97 | $allAddons = $this->db->fetchAll($select);
98 | $result = NULL;
99 | foreach ($allAddons as $row) {
100 | $len = Typecho_Common::strLen($row['name']);
101 | $cmd = Typecho_Common::substr($this->postObj->Content, 0, $len, '');
102 | if(Typecho_Common::strLen($this->postObj->Content) > $len && $cmd === $row['name'] && $row['param']){
103 | $result['value'] = $this->postObj->Content;
104 | $result['cmd'] = $cmd;
105 | $result['param'] = Typecho_Common::substr($this->postObj->Content, $len, Typecho_Common::strLen($this->postObj->Content, ''));
106 | break;
107 | }
108 | }
109 | return $result;
110 | }
111 |
112 | /**
113 | * 第三方平台
114 | */
115 | public function thirdParty(){
116 | $postStr = file_get_contents("php://input");
117 | $params['signature'] = $this->options->WCH_thirdPartyToken;
118 | $params['timestamp'] = time();
119 | $params['nonce'] = rand(100000000, 999999999);
120 |
121 | $client = Typecho_Http_Client::get();
122 | $response = $client->setHeader('Content-Type', 'text/xml')
123 | ->setHeader('User-Agent', $this->useragent)
124 | ->setQuery($params)
125 | ->setData($postStr)
126 | ->send($this->options->WCH_thirdPartyUrl);
127 | $this->result->setSendContent($response)->setMsgType(MessageTemplate::THIRD)->send();
128 | }
129 |
130 | /**
131 | * 博客日志数据
132 | */
133 | public function blogPost($action){
134 | $result = $this->$action();
135 | foreach ($result as $row) {
136 | $row = Typecho_Widget::widget('Widget_Abstract_Contents')->filter($row);
137 | $item['title'] = $row['title'];
138 | $item['description'] = Typecho_Common::subStr(str_replace("\n", '', trim(strip_tags($row['text']))), 0, 100, '...');
139 | //$item['description'] = Typecho_Common::subStr(trim(strip_tags($this->excerpt)), 0, 100, '...');
140 | //$item['picurl'] = 'https://www.google.com/images/srpr/logo11w.png';
141 |
142 | $img = array();
143 | $image = '';
144 | if(0 === strpos($row['text'], '')){
145 | echo 'yes';
146 | }else{
147 | preg_match('/("|\'|\(|(:\s)|=)(http:\/\/(.*?)\.(jpg|gif|png|bmp))/i', $row['text'], $img);
148 | if(count($img)){
149 | preg_match('/^(.*?)h/is', $img[0], $prefix);
150 | if(!isset($prefix[1])) $prefix[1] = '';
151 | $image = str_replace($prefix[1], '', $img[0]);
152 | }
153 | }
154 |
155 | //print_r($image);
156 |
157 | $item['picurl'] = $image;
158 | $item['url'] = $row['permalink'];
159 | $this->result->addItem($item);
160 | }
161 | $this->result->setMsgType(MessageTemplate::NEWS)->send();
162 | }
163 |
164 | private function sysGeneralSql(){
165 | $sql = $this->db->select()->from('table.contents')
166 | ->where('table.contents.status = ?', 'publish')
167 | ->where('table.contents.created < ?', $this->options->gmtTime)
168 | ->where('table.contents.type = ?', 'post')
169 | ->where('table.contents.password IS NULL');
170 | return $sql;
171 | }
172 |
173 | /**
174 | * 最新日志
175 | */
176 | private function sys_recent(){
177 | $sql = $this->sysGeneralSql()->order('table.contents.created', Typecho_Db::SORT_DESC)->limit(5);
178 | $result = $this->db->fetchAll($sql);
179 | return $result;
180 | }
181 |
182 | /**
183 | * 随机日志
184 | */
185 | private function sys_random(){
186 | $sql = $this->sysGeneralSql()->limit(5)->order('RAND()');
187 | $result = $this->db->fetchAll($sql);
188 | return $result;
189 | }
190 |
191 | /**
192 | * 热评日志
193 | */
194 | private function sys_hot_comment(){
195 | $sql = $this->sysGeneralSql()->order('table.contents.commentsNum', Typecho_Db::SORT_DESC)->limit(5);
196 | $result = $this->db->fetchAll($sql);
197 | return $result;
198 | }
199 |
200 | public function addonsAction($action, $postObj, $params = NULL){
201 | $file = __TYPECHO_ROOT_DIR__ . '/' . __TYPECHO_PLUGIN_DIR__ . '/WeChatHelper/Addons/'.$action.'/Addon.php';
202 | include_once $file;
203 | $info = Typecho_Widget::widget('WeChatHelper_Widget_Addons')->parseInfo($file);
204 | $class = 'Addons'.$info['package'];
205 | $addons = new $class($this->result, $postObj, $params);
206 | $addons->execute();
207 | }
208 |
209 | public function action() {
210 | $postStr = file_get_contents("php://input");//$this->request->get("HTTP_RAW_POST_DATA");
211 | if (!empty($postStr)){
212 | $this->response->setContentType("text/xml");
213 | $this->postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
214 | $this->result = new MessageTemplate($this->postObj);
215 | $exe = 'is'.ucwords($this->postObj->MsgType);
216 | if(method_exists($this, $exe)){
217 | $this->$exe();
218 | }
219 | }
220 | }
221 | }
222 |
--------------------------------------------------------------------------------