Tag: 微信

  • AI让我更强大

    AI让我更强大

    2007年1月17日的时候,我注册了我现在一直在用的域名rsywx.net。在2016年的时候,我启动了我现在用的这个订阅号。

    (我一直把这个订阅号叫做“任老师随便聊”,但前几天微信通知我,认为我的订阅号名字中“涉及教育行业领域相关职业、职位或职称”。我想来想去,应该是“老师”这两个字。我也懒得和微信计较了,所以干脆改个名字到“老任随便聊”。

    不过还是说一点感受。

    我一直认为,最广义上的“教育”不是一个专属的“职业、技能”。按照我自己研究出来的最小干预模型(Least Disturbance Model,或LDM)的要求,更合理的做法你可以取这个名字,但如果被投诉,就核实并制裁。

    我没想到,微信从另外一个角度来贯彻这个LDM。

    Anyway… )

    ===以下是正文===

    前两天下载了一个用来开发程序的IDE,Windsurf。IDE我用过不少,比如赫赫有名的Visual Studio Code,后起之秀Cursor,比起我刚开始写程序时用的IDE,不知道高到哪里去了。

    我开始是抱着试试看的态度试用Windsurf,让它帮我生成了几个小程序,效果都还不错,几乎都能做到一次成功。

    于是我就萌生了让它帮我写我的微信订阅号后台的想法——然后,我发现,这是一个轻松而愉快的过程!

    和AI讨论的第一步,当然是让它进入角色,所以我问它:你是不是熟悉微信订阅号的开发?它的回答是令人安心的。

    后续的工作也一样简单:基本的框架文件是AI生成的,需要填写的一些敏感信息AI当然无法获得,但它很正确地告诉我从哪里去获得这些内容:

    在这个过程中,AI也在不断试错——毕竟,原则不变,但每个开发环境都各不相同——但总体来说,我没有“动什么脑筋”,就完成了最重要的微信交互第一步:开放我的域名并让微信认可。

    第一步完成后就很快了。我开始要求AI加入功能,这个过程也很直截了当。

    目前,我的订阅号支持三个功能1,并需要相应的关键词激活:

    • QOTD:Quote of The Day。激活词是:“QOTD”,“每日一句”,“名言”。
    • BOTD:Book of The Day。激活词是:“BOTD”,“每日图书”,“图书”,“书”。
    • WOTD:Word of The Day。激活词是“WOTD”,“每日单词”,“单词”。

    进入我的微信订阅号(“老任随便聊”),输入这些激活词,就能获得相应的反馈。如下就是一个BOTD的反馈:

    如何?还算可以吧?

    这些功能,我大概用了晚上2个小时左右就完成了。

    =========

    From the hindsight

    1. 对于编程这样目标明确,测试(有没有达到目标)手段明确的任务来说,AI确实已经全面碾压人类。
    2. 作为我来说,我能这么快地完成这个任务,有两个因素(或者说“基础”)在帮忙:
      1. 一个是,我一直在思考这些功能,而我之前多年的积累,也让我能迅速指导AI进行怎样的工作。AI在知道我要干嘛后,提出的一些功能有用,但毕竟我最知道我的要求。
      2. 另一个是,我有足够的编程基础,所以能避开AI给出的一些坑。
    3. 我从一个开发者牛马,变成了一个“老板”。我更多地在说What,而不再关心How。这个和我之前当PM的时候有点像,唯一不同的是,我不需要向AI解释Why。
    4. 从繁重的daily issue解脱后,我才能思考我想要什么。这是人的创造力的源泉,做事情的动力。也是AI目前最能帮助我们的地方。这样的生产力解放,是我乐意看到的。
  • 无限期停止朋友圈

    之前,我曾经关闭过一次我的朋友圈,然后又重新激活了。今天,我要再次无限期关闭我的朋友圈。

    起因很简单:

    以上是我第一次发帖后,我的朋友圈我朋友的朋友圈。

    以上是我第二次发帖后,我的朋友圈我朋友的朋友圈。

    2月7日不幸逝世的李文亮医生生前说过,一个健康的社会不应该只有一种声音。

    这段艰难的时间里,我在朋友圈也见证了众多三观不合的言论。我虽然可以相信他们在转发的时候多出于无意,但我觉得继续忍受这样的言论是种痛苦。

    特此宣布,无限期关闭我的朋友圈。其他我加入的群目前还正常使用。有事可以私信联系。

  • 微信公众号、各类应用的隐私问题

    不知道最近大家是否在微信中收到过这么一条信息:

    IMG_0556

    我不知道发出这条消息的那位微信好友是出于什么目的:是真心地认为自己微信好友太多,也真心地认为不知出于什么原因被僵尸粉看上了,或者被别人屏蔽了,所以要从中知道自己真正的粉有多少;还是出于什么商业推广目的,因为在这条消息中明确出现了一个所谓平台的微信号;还是因为被感染了什么微信病毒,在自己不知情的情况下发送了这么一条信息;还是脑子进了水,根本没有对自己微信好友的隐私的保护?

    我的判断是:这位我的微信好友脑子进了水,相信了这种莫名其妙的平台提供的莫名其妙的服务,然后加了这个平台,给出了让这个平台访问自己所有微信好友(甚至可能包括手机通讯录)的权限,然后平台自动地开始发送这样的垃圾信息。

    别的我不多说。我想对这些TYTSTN的用户提醒一句:

    我和你,不管出于什么原因,成了微信上的好友。对此,你获知了我的个人数据:微信号(很多时候还是手机号),可以访问我的朋友圈以及朋友圈上所有公开的消息,以及这些消息中包含的我的个人数据。

    但是,我授权或者说允许你看到这些个人数据,并不意味着我同时授权你将我的个人数据与任何第三方分享!这是对我的隐私的赤裸裸的侵犯,你知道吗?

    对方得到我的个人数据,会派什么用途?你知道吗?

    打个不恰当的比方,我和你是朋友,你有一个我不认识的朋友对你说,来啊,把你的朋友介绍给我吧,我让他们发财。你在给出我的电话号码前,是不是应该问问他准备用什么方法让我发财?是不是应该问问我是不是有兴趣?而在得到我明确的同意之后,再将我的电话号码告诉你的这位朋友?

    到了网络之后,怎么连这点基本的规矩都不懂了呢?

    对不起……我撤回刚才那句话。不是你到了网络之后,不懂这些基本的规矩……而是因为在现实生活中,你连这点基本的规矩也不懂!是我错怪了你。

    还有微信,是不是出于CSR,拿点实实在在、严严厉厉的行动出来?

    说句题外话,在中国大陆,我真的不愿意从事所谓的互联网创新。一个没有底线、没有法律、也根本没有正常的商业运作的环境中,自然只有恶人在肆虐。我的道德操守不允许我这么做。

  • 微信订阅号的开发

    最近看了一下微信订阅号的开发。

    我要做一个个人订阅号,用户订阅之后,可以通过输入命令获得交互,得到英文单词的解释,大概就是这样。

    微信开发权限获得就不讲了,需要帮助的同学可以去访问相应的站点。

    首先,我开了一个域名(http://weixin.rsywx.com) 作为和微信通讯的接口。

    按照微信的说法,用户输入命令后,该接口将“被动”地回复信息。而这也是我这个订阅号和用户交互的主要渠道。

    在weixin.rsywx.com中,我用Silex框架构建了我的应用。这是因为我需要在这个框架中进行一些控制。当然你也可以用一个plain PHP文件来完成这个接口的工作。 该应用的入口文件很简单:

    require_once __DIR__ . '/../vendor/autoload.php';
    require_once __DIR__ . '/./WechatCallbackAPI.php';
    $app = new Silex\Application();
    $app['debug'] = true;
    // Twig registration
    $app->register(new Silex\Provider\TwigServiceProvider(), ['twig.path' => __DIR__ . '/../views']);
    $app->post('/', function () use ($app)
    {
        $obj=new WechatCallbackAPI();
        echo $res=$obj->response($app);
    });
    $app->run();

    其中的Twig注册不是必要的,因为微信要求的回应是一个XML字符串。不过放进去也没有关系。 对于“/”这个路径,我们在响应微信的请求时必须使用POST方式。同时我们创建了一个对象,并调用response方法来返回消息。 在WechatCallbackAPI中,我们抄袭微信的实例代码并作一些改进:

    public function response($app)
        {
            $post=$GLOBALS['HTTP_RAW_POST_DATA'];
            //$post=file_get_contents('php://input');
            if(!empty($post))
            {
                libxml_disable_entity_loader(true);
                $obj=simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);
                $from=$obj->FromUserName;
                $to=$obj->ToUserName;
                $key=strtolower(trim($obj->Content));
                if($key==?||$key==?||$key=='help')
                {
                    $wpme=new WPME($from, $to);
                    $res=$wpme->help();
            return $res;
                }
                else if (substr($key, 0,4)=='wpme')
                {
                    $wpme=new WPME($from, $to);
                    $wpme->setKey($key);
                    $res=$wpme->invoke();
                    return $res;
                }
                else if(substr($key, 0,4)=='wotd')
                {
                }
                else
                {
                    $wpme=new WPME($from, $to);
                    $res=$wpme->unknown();
                    return $res;
                }
            }

    注意,这里还用到了一个在PHP 5.6中被标记为deprecated,而在PHP 7将是obsolete的功能:

    $post=$GLOBALS['HTTP_RAW_POST_DATA'];

    PHP手册中建议用

    <pre lang="php">$post=file_get_contents('php://input');

    但是经过测试似乎不行。微信就是这么任性。

    在该response函数中,我们根据不同的用户输入来调用不同的功能。上述代码中列出了WPME(Word Power Made Easy)模块中的判断。WPME模块中最重要的方法是invoke,它将根据不同的命令($key)去进一步调用不同的资源并构造返回值。而另外一些命令在WPME中直接处理,比如最简单的help方法:

    public function help()
        {
            $content = Available commands:\nwpme1: Latest WPME\nwpme7: Last 7 WPMEs\nwpme????: Search WPME for ????;
            $res = sprintf(WPME::$txtTemplate, $this->from, $this->to, time(), $content);
            return $res;
        }

    help将列出可以使用的命令,比如wpme1,然后渲染一个静态文本模板并返回。文本模块的格式可以参考微信文档。

    而invoke方法如下:

    public function invoke()
        {
            $uri = https://rsywx.net/wechat/ . htmlentities($this->key);
            $content = file_get_contents($uri);
            preg_match_all('/(.*?)<\/title>/i', $content, $matches);
            $res = sprintf(WPME::$newsTemplate, $this->from, $this->to, time(), $matches[1][0], date('Y-m-d'), $uri);
            return $res;
        }

    我们可以看到,我们的一般命令将返回图文信息。而图文信息的模板格式也请参考微信文档。这里我们并不进行任何实质性的处理,真正的内容渲染我们在另外一个站点:https://rsywx.net 中进行。

    rsywx.net是一个之前我单独开发的站点,考虑到微信使用的一些功能可以在该站点中复用,所以我将微信需要的返回信息的功能(控制、数据、呈现)放在这里实现。这个站点用Symfony完成。其实,我这个微信号最本质的内容呈现逻辑都是在rsywx.net中完成的。

    我们看一个indexAction方法。这个方法接受来自weixin.rsywx.com的调用,并根据不同的关键字进行处理:

    public function indexAction($key)
        {
            $entity = substr($key, 0, 4);
            if ($entity == 'wpme')
            {
                if ($key == 'wpme1' || $key == 'wpme7')
                {
                    $uri = http://api/$entity/$key;
                    $res = json_decode(file_get_contents($uri))->out;
                    $theme = $this->container->getParameter('theme');
                    return $this->render(AppBundle:$theme/wechat:$key.html.twig, ['res' => $res->res]);
                }
                else //The key is like wpme????, where ???? is the search term
                {
                    $search = substr($key, 4);
                    $uri = http://api/$entity/s/$search;
                    $res = json_decode(file_get_contents($uri))->out;
                    $theme = $this->container->getParameter('theme');
                    return $this->render(AppBundle:$theme/wechat:wpme7.html.twig, ['res' => $res->res]);
                }
            }
        }

    如果从weixin传来的命令是wpme1(列出最新的单词)或者wpme7(列出7个最新的单词),那么rsywx.net将进一步调用http://api.rsywx.com 中相应的RESTful API接口获得数据并渲染;如果是类似wpme????这样的命令,那么将进行搜索,并将结果返回。

    最后我们来看http://api.rsywx.com ,如果我们直接访问这个站点,将会呈现该站点所提供的所有接口的API文档:

    Ashampoo_Snap_2016.02.01_20h46m03s_002_Chrome

    而在这个站点中,我同样用Silex框架实现了对应的方法来返回数据(实际上,rsywx.net的所有数据也都是由该站点提供的)。

    好了,如果你现在在公众号中输入这样的一个命令:wpme1,你将看到如下的界面:

    Screenshot_20160201-205011

    Screenshot_20160201-205018

    怎么样?是不是很酷?

    本文收录于[go4pro.org]

  • 我关闭了微信朋友圈

    昨天决定关闭微信朋友圈。

    有这么几个原因。

    1. 关闭朋友圈不会影响我收发红包。
    2. 朋友圈的设计不是用来扩展朋友圈,而是限制朋友圈。
    3. 转发机制很不友好。
    4. 最近微信朋友圈推广的一些活动让我很不耻。

    不过我还是会维护微信订阅号。

  • 从博客到微信

    Guns写了一篇博客,题为《从博客到微信-论科技的进步和文化的退化》,并邀请我写点康蒙特。

    这篇就是了。

    博客死了吗?还有人说RSS已经死了。我认为Guns这句话说到了点子上:

    博客有一层文化上面的深度 这个是微信不可取代的

    我是一个老派的互联网用户,我消费信息,但我更喜欢生产信息。所以,我很少玩非博客的SNS——饭否除外。

    微信我就更少用了。因为我向来不喜欢在手机上输入文字。手机屏幕小、键盘不好用、再加上近年来老花严重,我还是喜欢在电脑上书写。所以,如果一个SNS没有桌面端的应用(不是那种需要登录到界面里操作的WEB界面,而是像Fawave、Gohan这样集成在浏览器或者独立的应用),我就注定只能当一个消费者,而消费来消费去,就没有了一开始的新鲜感和冲动,于是就更沉默了。

    微博是什么?更多的人现在用来即时通讯。那天在浦东机场准备出发去越南的时候,公司的姑娘们显然各个身负重任,用微信在和姐妹们联络:“我这里看到日上的XXX牌护肤霜是YYY元,ZZZ毫升。你要吗?”

    在即时性方面,微信是完胜博客的,有人甚至说那是完美的——但这是一个太轻易而得到的结论。

    在我看来,除了面对面交流或者打电话之外,所有的沟通形式都不是即时的,因为所有这些SNS的“即时”性都基于这样的一个假设:对方在线并做好准备来接收你的信息。

    电话呢?对方可能不在线(比如关机、无信号),但是SNS在这种情况下也是不在线,而且你还不能知道这种情形。所以SNS的所谓即时性需要三个前提:对方在线、对方准备接收你的信息、对方准备回复你的信息。这三个前提缺一不可。

    在我看来,SNS更多的是应该抛出一个话题,并引导感兴趣的读者进一步消费更详细的信息(比如给出一篇博客的连接、一个照片的连接等)。只要这个应用范式还在,那么博客就不会消亡。而更多的应用内置了诸如“共享到……”的选择反过来为信息的产生——更精确的说是信息的共享——提供了更便捷的手段,免去我在手机键盘上辛苦码字的烦恼,从而能更快地共享出信息。

    当然,随着网络覆盖的越来越普及,人们将越来越可以随时保持在线。抛开耗电、费流量不说,这没有什么坏处。

    我真的不是一个SNS的人。