2
jox 2014-12-13 20:48:55 +08:00 1
如果需要验证并且需要严肃处理的话,需要分析字符串,然后用语法规则匹配,匹配得到结果之后验证是否是有效的账户,是的话选择高亮并进入提醒逻辑,不是的话就不管。
如果用户不是很多,也不用考虑验证的问题,直接简单粗暴地用正则表达式去匹配,得到结果就进入提醒逻辑,否则就不管 |
4
lincanbin 2014-12-13 20:50:33 +08:00 1
https://github.com/lincanbin/Carbon-Forum/blob/master/common.php#L54
我自己的实现就是这样的,不这样做要怎么做? |
5
jox 2014-12-13 20:56:32 +08:00 1
@dong3580 他们大概会做严肃的分析吧,也可能不会。我看新浪微博如果是 @@用户名 这样的是不会触发提醒的,也可能他们只是做简单的正则匹配,反正这个东西无所谓的吧,因为如果匹配失败的话发出去的微博就是普通的字符串,用户看见了就知道失败了,如果需要重新@的话就让用户重新弄一遍,我觉得没什么,正则匹配应该就够用了,性能方面也不是问题。腾讯微博我不知道,我因为最近开始使用v2ex才去申请了个新浪微博作为图床。
|
6
dong3580 2014-12-13 21:01:34 +08:00 1
@jox
猜测,@是不是只是一个被动的标志,普通的数据库(缓存)保存。用户只有刷新页面,才会收到@自己的消息或者留言(主动推送另当别论),这样,就像普通的查询数据库(缓存)一样。 至于上面童鞋说的正则匹配文本,似乎觉得效率会有问题。 事实上我并没做过类似的功能,仅仅是猜测。 |
8
jox 2014-12-13 21:09:15 +08:00 1
@dong3580 应该就是每个用户有个数据结构,类似队列那样的数据结构,被@的用户浏览某个或者某些特定的网页会消耗这个数据结构里的item,比如v2ex只有点开提醒那个页面才会消灭这些提醒,如果用户永远不点开,那么这个数据结构里的item就永远都不会消耗,伴随着用户直到他死去。每个item有自己的数据结构,里面可以保存url之类的数据,至于前端怎么展示,那就是前端的问题了,后端的逻辑应该就是这样的。
|
9
jox 2014-12-13 21:13:51 +08:00 1
@dong3580 正则匹配文本的效率不会是问题,从头到尾挨个字符遍历一遍就行了,这个过程可以非常快,疯狂的快,快到让人受不了!现在大点儿的互联网公司,这种操作对他们的服务器来说简直就是可以忽略到使劲掐手指来形容“小”都无法描述出有多么微不足道的那种程度。
|
11
akira 2014-12-13 21:38:10 +08:00 1
也只能这么做了吧。。
|
12
rainday 2014-12-13 22:05:54 +08:00 1
在牛客网 http://www.nowcoder.com 用户在我们网站提交的评论,我们会进行敏感词过滤,其算法是基于有限状态机DFA过滤的。 我觉得可以用敏感词过滤的方法来查找@的用户ID。 (用户ID就是好多敏感词), 具体的代码如下:
<code> /** * 过滤敏感词 * * @param text * @return */ public String filter(String text) { if (StringUtils.isBlank(text)) { return text; } String replacement = DEFAULT_REPLACEMENT; StringBuilder result = new StringBuilder(); DFATreeNode tempNode = rootNode; int begin = 0; // 回滚数 int position = 0; // 当前比较的位置 while (position < text.length()) { char c = text.charAt(position); // 空格直接跳过 if (isSymbol(c)) { ++position; continue; } tempNode = tempNode.getSubNode(c); // 当前位置的匹配结束 if (tempNode == null) { // 以begin开始的字符串不存在敏感词 result.append(text.charAt(begin)); // 跳到下一个字符开始测试 position = begin + 1; begin = position; // 回到树初始节点 tempNode = rootNode; } else if (tempNode.isKeywordEnd()) { // 发现敏感词, 从begin到position的位置用replacement替换掉 result.append(replacement); position = position + 1; begin = position; tempNode = rootNode; } else { ++position; } } result.append(text.substring(begin)); return result.toString(); } </code> |
13
RelativeLayout 2014-12-13 22:47:40 +08:00 1
一个正则就搞定了,拿去用吧
/@([^\s@]+)/gi |
14
LukeXuan 2014-12-13 22:50:20 +08:00 1
不是一个基于trie的DFA就搞定了么……当然可以路径压缩一下速度更优……
|
15
imxz 2014-12-13 23:03:49 +08:00 1
正在继续写的BBS程序 http://letsbbs.com/ 实现逻辑基本如二楼所说,就是还没有加验证,直接往提醒系统里去了,这要谢谢 @jox 提醒,回头加上验证。
相关代码: https://github.com/imxz/LetsBBS/blob/master/application/controllers/comment.php 希望高人来谈一谈,这样做是不是合理。 |
17
jox 2014-12-14 10:22:56 +08:00 via iPhone 1
@zzutmebwd 这个就看开发者怎么取舍了吧 看你把某个昵称的作用范围定为多大和你想拿@昵称用来干啥了 如果你说你要像微博那样拿一个昵称去@某用户 这个昵称既和发起@的用户没有任何联系同时还存在好多个用户拥有相同昵称 这是不能确定唯一的 同时这种功能也是没有意义的 但如果限定@昵称的作用范围就好办了 比如好友或者同一页面内的评论用户 如果作用域内存在重复 就捕捉用户的输入事件 提供个包含不同个体的菜单 用户必须在菜单内选择某选项@才会生效 否则就视为普通字符串
|
20
lincanbin 2014-12-14 12:11:45 +08:00 1
@ultraqs 使用带参数绑定的数据库类,例如PDO或者MySQLi,这样命令和参数分离,也就无法在参数中构造命令。
直接搞引号过滤之类的是再愚蠢不过了。 这是我封装的PDO类: https://github.com/lincanbin/PHP-PDO-MySQL-Class |
21
c4pt0r 2014-12-14 14:23:16 +08:00 1
发帖的时候正则,提取出 @ 然后把帖子的 id 丢到一个提醒的队列里(这里的队列可以是数据库的一个表,Redis Queue,whatever)。
然后通知一下在线的客户端(or web)的长连接,让客户端过来拉取这是 push 的方式,长连接不想做的话换成 pull 的方式也行 。 |
22
iugo 2014-12-16 14:36:43 +08:00 1
我觉得用 PHP 实现得比较好的是 esoTalk 这个东西.
https://github.com/esotalk/esoTalk |