@小二 #10 最近感觉不行。有空我去试试。我不是大神,你才是
-
中文互联网中“讨论”的消亡
@饱读书名 #52 去中心化存储访问。我的理解。ipfs那样吧?
-
今天量体温,37.8度
另外一个女孩子是我的学妹。长得是很漂亮,就是不知道为什么脾气那么差,老是打我。
不过也就是拳头锤几下,也不疼。不过对我总是用吼的,态度也不好。
但是,她其实对我有种很奇怪的感觉吧。我生日,她也会订蛋糕。。。
额外一点,去年我生日,她专门去学了织围巾。她亲手织了围巾送给我。记得当时天很冷,她约我出来,把围巾送给我,还对我说,这是她一生中第一次织围巾,她想把这个送给我,当作毕业留念吧,也当作生日礼物。
我说实话,第一次收到女生亲手制作的生日礼物。我也对她有好感啊。其实她为了我的生日礼物,专门去学习织围巾,我挺开心的。相对于我女友,我感觉她付出挺多的。
我也追过她,但是她对我态度,和女友比,就是两个字“暴力”!
感觉还是吃不消。
-
今天量体温,37.8度
我想起张爱玲的《红玫瑰与白玫瑰》。
张爱玲在开篇就说,也许每一个男子全都有过这样的两个女人,至少两个。娶了红玫瑰,久而久之,红的变了墙上的一抹蚊子血,白的还是“床前明月光”;娶了白玫瑰,白的便是衣服上沾的一粒饭粘子,红的却是心口上一颗朱砂痣。
我不知道大家的选择是什么,但是我选择了白月光,她是一个永远成为不了朱砂痣的女人。未来对我就是白米粒。
朱砂痣,她也不会成为蚊子血,和她在一起,青春,热血,潮气蓬勃。火爆脾气吧,是唯一的缺点了。有些事情只能埋藏心底。
一生可以得到两个我觉得对我不差的女生的好感。我觉得这辈子挺值得的。
可惜她们两个不知道我内心的矛盾,选择的时候,我有种内疚。
不是因为没选择另一个而对她内疚,而是我连自己想娶谁都要做选择题,我感觉对爱情不忠。所以内疚
明明只可能爱一个女人,心里应该早有答案,为什么要朝三暮四,脚踩两条船,所以内疚
而且我现在也不敢把自己微信密码告诉我女朋友。。。
我在想,是我删了她的微信以后,再把密码给女朋友,还是应该和她坦白自己已经有女朋友了,再把密码给女朋友?
脑袋都要炸了!
-
今天量体温,37.8度
女人就是很复杂。
大二,我在学校里不小心摔倒了,裤子破了,膝盖流了血。她过来帮我,后来还帮我缝了裤子,我们就这么认识了。
我以为她喜欢我呢,我就追她。但是她不答应。也不收我礼物。但是却在我生日的时候,总是给我订蛋糕。
虽然不会陪我过生日,也不让我碰她,所以连牵手也没有,
她后来和我说喜欢一个学长,周末要去和他打羽毛球。然后就没有然后了。。。。
现在我们都要毕业了,她和学长什么情况我不知道,我只知道她说喜欢我,想和我交往
我其实,也想知道她和学长发生了什么没有。算了,就当自己什么都不知道吧。她在我印象里,很保守,不让男生碰的。。。反正我想和她牵手,她都不答应
-
今天量体温,37.8度
@小二 #2 我和保安说是设备坏了
但是我用温度计也有37度了
还是自己家里隔离下吧
-
今天量体温,37.8度
我女朋友对我很冷淡!我找她约会,从来不答应。
但是自己很喜欢她啊。她老说我不会哄女孩子。
以前从来不说我是她男朋友,最近突然对我表白,我们就成为了男女朋友。
她要我帮她做毕业设计。
我是真不懂化学啊
-
中文互联网中“讨论”的消亡
@饱读书名 #49 你说的这个东西就是TOR
-
2049增加Google验证码代码
@yourmom #7 何苦认为i我是小二呢?我可能真的发高烧了。。。得隔离了,你暂时见不到我了
-
utc 时间 13:30:00 停机维护,大约五分钟恢复正常。
想想还是php好,改完代码直接ftp上传就生效了,因为是脚本。
golang因为是编译型语言,每次替换,都需要重启服务。
最好开个nginx作为前置,需要替换的时候,nginx还可以给个静态网页说在服务器升级,而不是521报错
-
今天量体温,37.8度
我感觉,头晕,发热,不舒服,而且拉肚子。
进出小区保安量体温37.8度,我和保安说是设备坏了,让他去修下,他就放我进小区了。
我想休息一会了。下周估计也没法入职了!!!
也没法帮女朋友写毕业论文了。。。还有好多事情没有做。。。
-
2049bbs有onion地址么?刚才看到了
@小二 #2 我测试了很多遍,无法复现刚才这个现象。
应该是cloudflare的bug吧。
你没有在服务器上部署tor,应该不可能出现刚才的提示。
应该是cloudflare提示的
alt-svc h3-27=":443"; ma=86400, h3-25=":443"; ma=86400, h3-24=":443"; ma=86400, h3-23=":443"; ma=86400这个字符串,出现了一个xxxxxxx.onion:443 这样的地址
-
2049bbs有onion地址么?刚才看到了
alt-svc: h2="cflareub6dtu7nvs3kqmoigcjdwap2azrkx5zohb2yk7gqjkwoyotwqd.onion:443"; ma=86400; persist=1
-
2049bbs有onion地址么?刚才看到了
cat /var/lib/tor/hidden_service/hostname执行上面这个命令,小二应该就可以看到2049bbs.xyz的onion域名了
-
2049bbs有onion地址么?刚才看到了
刚才打开2049bbs的时候,提示了一个cfluare打头的onion地址。我还没有保存,这个地址就没了
有人知道么?
-
rss 不输出树洞、水区和垃圾场内容
树洞、水区和垃圾场at无效
https://github.com/Terminus2049/2049bbs/issues/8
修改代码 https://github.com/Terminus2049/2049bbs/blob/master/controller/article.go
package controller import ( "crypto/md5" "encoding/hex" "encoding/json" "html/template" "math/rand" "net/http" "strconv" "strings" "time" "github.com/ego008/youdb" "github.com/rs/xid" "github.com/terminus2049/2049bbs/model" "github.com/terminus2049/2049bbs/util" "goji.io/pat" ) func (h *BaseHandler) ArticleAdd(w http.ResponseWriter, r *http.Request) { cid := pat.Param(r, "cid") _, err := strconv.Atoi(cid) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"cid type err"}`)) return } currentUser, _ := h.CurrentUser(w, r) if currentUser.Id == 0 { w.Write([]byte(`{"retcode":401,"retmsg":"authored err"}`)) return } if currentUser.Flag < 5 { var msg string if currentUser.Flag == 1 { msg = "注册验证中,等待管理员通过" } else { msg = "您已被禁用" } w.Write([]byte(`{"retcode":401,"retmsg":"` + msg + `"}`)) return } db := h.App.Db cobj, err := model.CategoryGetById(db, cid) if err != nil { w.Write([]byte(`{"retcode":404,"retmsg":"` + err.Error() + `"}`)) return } type pageData struct { PageData Cobj model.Category MainNodes []model.CategoryMini } tpl := h.CurrentTpl(r) evn := &pageData{} evn.SiteCf = h.App.Cf.Site evn.Title = "发表文章" evn.IsMobile = tpl == "mobile" evn.CurrentUser = currentUser evn.ShowSideAd = true evn.PageName = "article_add" evn.Cobj = cobj evn.MainNodes = model.CategoryGetMain(db, cobj) h.SetCookie(w, "token", xid.New().String(), 1) h.Render(w, tpl, evn, "layout.html", "articlecreate.html") } func (h *BaseHandler) ArticleAddPost(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") token := h.GetCookie(r, "token") if len(token) == 0 { w.Write([]byte(`{"retcode":400,"retmsg":"token cookie missed"}`)) return } currentUser, _ := h.CurrentUser(w, r) if currentUser.Id == 0 { w.Write([]byte(`{"retcode":401,"retmsg":"authored require"}`)) return } if currentUser.Flag < 5 { w.Write([]byte(`{"retcode":403,"retmsg":"user flag err"}`)) return } type recForm struct { Act string `json:"act"` Cid uint64 `json:"cid"` Title string `json:"title"` Content string `json:"content"` } decoder := json.NewDecoder(r.Body) var rec recForm err := decoder.Decode(&rec) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"json Decode err:` + err.Error() + `"}`)) return } defer r.Body.Close() rec.Title = strings.TrimSpace(rec.Title) rec.Content = strings.TrimSpace(rec.Content) db := h.App.Db if rec.Act == "preview" { tmp := struct { normalRsp Html string `json:"html"` }{ normalRsp{200, ""}, util.ContentFmt(db, rec.Content), } json.NewEncoder(w).Encode(tmp) return } // check title hash := md5.Sum([]byte(rec.Title)) titleMd5 := hex.EncodeToString(hash[:]) if db.Hget("title_md5", []byte(titleMd5)).State == "ok" { w.Write([]byte(`{"retcode":403,"retmsg":"title has existed"}`)) return } now := uint64(time.Now().UTC().Unix()) scf := h.App.Cf.Site if currentUser.Flag < 99 && currentUser.LastPostTime > 0 { if (now - currentUser.LastPostTime) < uint64(scf.PostInterval) { w.Write([]byte(`{"retcode":403,"retmsg":"PostInterval limited"}`)) return } } if rec.Cid == 0 || len(rec.Title) == 0 { w.Write([]byte(`{"retcode":400,"retmsg":"missed args"}`)) return } if len(rec.Title) > scf.TitleMaxLen { w.Write([]byte(`{"retcode":403,"retmsg":"TitleMaxLen limited"}`)) return } if len(rec.Content) > scf.ContentMaxLen { w.Write([]byte(`{"retcode":403,"retmsg":"ContentMaxLen limited"}`)) return } newAid, _ := db.HnextSequence("article") aobj := model.Article{ Id: newAid, Uid: currentUser.Id, Cid: rec.Cid, Title: rec.Title, Content: rec.Content, AddTime: now, EditTime: now, ClientIp: "", } jb, _ := json.Marshal(aobj) aidB := youdb.I2b(newAid) db.Hset("article", aidB, jb) // 总文章列表 ignorenodes := scf.NotHomeNodeIds if len(ignorenodes) > 0 { for _, node := range strings.Split(ignorenodes, ",") { node, err := strconv.Atoi(node) if err == nil && aobj.Cid != uint64(node) { db.Zset("article_timeline", aidB, aobj.EditTime) } } } // 分类文章列表 db.Zset("category_article_timeline:"+strconv.FormatUint(aobj.Cid, 10), aidB, aobj.EditTime) // 用户文章列表 db.Hset("user_article_timeline:"+strconv.FormatUint(aobj.Uid, 10), youdb.I2b(aobj.Id), []byte("")) // 分类下文章数 db.Zincr("category_article_num", youdb.I2b(aobj.Cid), 1) currentUser.LastPostTime = now currentUser.Articles++ jb, _ = json.Marshal(currentUser) db.Hset("user", youdb.I2b(aobj.Uid), jb) // title md5 db.Hset("title_md5", []byte(titleMd5), aidB) // send task work // get tag from title if scf.AutoGetTag { db.Hset("task_to_get_tag", aidB, []byte(rec.Title)) } // @ somebody in content if rec.Cid != 19 && rec.Cid != 20 { sbs := util.GetMention(rec.Content, []string{currentUser.Name, strconv.FormatUint(currentUser.Id, 10)}) aid := strconv.FormatUint(newAid, 10) for _, sb := range sbs { var sbObj model.User sbu, err := strconv.ParseUint(sb, 10, 64) if err != nil { // @ user name sbObj, err = model.UserGetByName(db, strings.ToLower(sb)) } else { // @ user id sbObj, err = model.UserGetById(db, sbu) } if err == nil { if len(sbObj.Notice) > 0 { aidList := util.SliceUniqStr(strings.Split(aid+","+sbObj.Notice, ",")) if len(aidList) > 100 { aidList = aidList[:100] } sbObj.Notice = strings.Join(aidList, ",") sbObj.NoticeNum = len(aidList) } else { sbObj.Notice = aid sbObj.NoticeNum = 1 } jb, _ := json.Marshal(sbObj) db.Hset("user", youdb.I2b(sbObj.Id), jb) } } } h.DelCookie(w, "token") tmp := struct { normalRsp Aid uint64 `json:"aid"` }{ normalRsp{200, "ok"}, aobj.Id, } json.NewEncoder(w).Encode(tmp) } func (h *BaseHandler) ArticleHomeList(w http.ResponseWriter, r *http.Request) { btn, key, score := r.FormValue("btn"), r.FormValue("key"), r.FormValue("score") if len(key) > 0 { _, err := strconv.ParseUint(key, 10, 64) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"key type err"}`)) return } } if len(score) > 0 { _, err := strconv.ParseUint(score, 10, 64) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"score type err"}`)) return } } cmd := "zrscan" if btn == "prev" { cmd = "zscan" } db := h.App.Db scf := h.App.Cf.Site pageInfo := model.ArticleList(db, cmd, "article_timeline", key, score, scf.HomeShowNum*2, scf.TimeZone, scf.NotHomeNodeIds) currentUser, _ := h.CurrentUser(w, r) // 首页第二栏节点 if currentUser.Theme != "2" { cid := scf.HomeNode cobj, err := model.CategoryGetById(db, cid) if err == nil { cobj.Articles = db.Zget("category_article_num", youdb.I2b(cobj.Id)).Uint64() pageInfo2 := model.ArticleList(db, cmd, "category_article_timeline:"+cid, key, score, scf.HomeShowNum, scf.TimeZone, "") pageInfo.Items = append(pageInfo.Items, pageInfo2.Items...) } } type siteInfo struct { Days int UserNum uint64 NodeNum uint64 TagNum uint64 PostNum uint64 ReplyNum uint64 } type pageData struct { PageData SiteInfo siteInfo PageInfo model.ArticlePageInfo Links []model.Link Announcement string Proverb template.HTML } si := siteInfo{} rs := db.Hget("count", []byte("site_create_time")) var siteCreateTime uint64 if rs.State == "ok" { siteCreateTime = rs.Data[0].Uint64() } else { rs2 := db.Hscan("user", []byte(""), 1) if rs2.State == "ok" { user := model.User{} json.Unmarshal(rs2.Data[1], &user) siteCreateTime = user.RegTime } else { siteCreateTime = uint64(time.Now().UTC().Unix()) } db.Hset("count", []byte("site_create_time"), youdb.I2b(siteCreateTime)) } then := time.Unix(int64(siteCreateTime), 0) diff := time.Now().UTC().Sub(then) si.Days = int(diff.Hours()/24) + 1 si.UserNum = db.Hsequence("user") si.NodeNum = db.Hsequence("category") si.TagNum = db.Hsequence("tag") si.PostNum = db.Hsequence("article") si.ReplyNum = db.Hget("count", []byte("comment_num")).Uint64() // fix if si.NodeNum == 0 { newCid, err2 := db.HnextSequence("category") if err2 == nil { cobj := model.Category{ Id: newCid, Name: "默认分类", About: "默认第一个分类", } jb, _ := json.Marshal(cobj) db.Hset("category", youdb.I2b(cobj.Id), jb) si.NodeNum = 1 } // link model.LinkSet(db, model.Link{ Name: "youBBS", Url: "https://www.youbbs.org", Score: 100, }) } tpl := h.CurrentTpl(r) evn := &pageData{} evn.SiteCf = scf evn.Title = scf.Name evn.Keywords = evn.Title evn.Description = scf.Desc evn.IsMobile = tpl == "mobile" evn.CurrentUser = currentUser evn.ShowSideAd = true evn.PageName = "home" evn.HotNodes = model.CategoryHot(db, scf.CategoryShowNum, scf.MustLoginNodeIds) if currentUser.IgnoreNode != "" { for _, node := range strings.Split(currentUser.IgnoreNode, ",") { node, err := strconv.ParseUint(node, 10, 64) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"忽略节点id应为整数,请在设置中检查。"}`)) return } for i := 0; i < len(pageInfo.Items); i++ { if pageInfo.Items[i].Cid == node { pageInfo.Items = append(pageInfo.Items[:i], pageInfo.Items[i+1:]...) i-- } } } } if currentUser.IgnoreUser != "" { for _, uid := range strings.Split(currentUser.IgnoreUser, ",") { uid, err := strconv.ParseUint(uid, 10, 64) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"忽略用户id应为整数,请在设置中检查。"}`)) return } for i := 0; i < len(pageInfo.Items); i++ { if pageInfo.Items[i].Uid == uid { pageInfo.Items = append(pageInfo.Items[:i], pageInfo.Items[i+1:]...) i-- } } } } // 类似 solidot 格言 if !evn.IsMobile { proverbs := model.CommentList(db, "hscan", "article_comment:"+scf.ProverbId, "", 500, scf.TimeZone, false) // 剔除折叠的回复 for i := 0; i < len(proverbs.Items); i++ { if proverbs.Items[i].Fold { proverbs.Items = append(proverbs.Items[:i], proverbs.Items[i+1:]...) i-- } } rand.Seed(time.Now().Unix()) if len(proverbs.Items) > 0 { evn.Proverb = proverbs.Items[rand.Intn(len(proverbs.Items))].ContentFmt } } evn.SiteInfo = si evn.PageInfo = pageInfo evn.Links = model.LinkList(db, false) // 公告板功能 uobj, err := model.UserGetById(db, 1) if err != nil { evn.Announcement = "公告板,可修改1号用户的个人简介进行修改。" } else { evn.Announcement = uobj.About } if currentUser.Theme == "2" && !evn.IsMobile { h.Render(w, tpl, evn, "layout.html", "index2.html") } else { h.Render(w, tpl, evn, "layout.html", "index.html") } } func (h *BaseHandler) ArticleDetail(w http.ResponseWriter, r *http.Request) { btn, key, score := r.FormValue("btn"), r.FormValue("key"), r.FormValue("score") if len(key) > 0 { _, err := strconv.ParseUint(key, 10, 64) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"key type err"}`)) return } } if len(score) > 0 { _, err := strconv.ParseUint(score, 10, 64) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"score type err"}`)) return } } aid := pat.Param(r, "aid") _, err := strconv.Atoi(aid) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"aid type err"}`)) return } cmd := "hscan" if btn == "prev" { cmd = "hrscan" } db := h.App.Db scf := h.App.Cf.Site aobj, err := model.ArticleGetById(db, aid) if err != nil { w.Write([]byte(err.Error())) return } currentUser, _ := h.CurrentUser(w, r) if len(currentUser.Notice) > 0 && len(currentUser.Notice) >= len(aid) { if len(aid) == len(currentUser.Notice) && aid == currentUser.Notice { currentUser.Notice = "" currentUser.NoticeNum = 0 jb, _ := json.Marshal(currentUser) db.Hset("user", youdb.I2b(currentUser.Id), jb) } else { subStr := "," + aid + "," newNotice := "," + currentUser.Notice + "," if strings.Index(newNotice, subStr) >= 0 { currentUser.Notice = strings.Trim(strings.Replace(newNotice, subStr, "", 1), ",") currentUser.NoticeNum = len(strings.Split(currentUser.Notice, ",")) jb, _ := json.Marshal(currentUser) db.Hset("user", youdb.I2b(currentUser.Id), jb) } } } if aobj.Hidden && currentUser.Flag < 1 { w.WriteHeader(http.StatusNotFound) w.Write([]byte(`{"retcode":404,"retmsg":"仅登录用户可见"}`)) return } cobj, err := model.CategoryGetById(db, strconv.FormatUint(aobj.Cid, 10)) if err != nil { w.Write([]byte(err.Error())) return } if cobj.Hidden && currentUser.Flag < 1 { w.WriteHeader(http.StatusNotFound) w.Write([]byte(`{"retcode":404,"retmsg":"仅登录用户可见"}`)) return } if cobj.Id == 20 && currentUser.Flag < 99 { w.WriteHeader(http.StatusNotFound) w.Write([]byte(`{"retcode":404,"retmsg":"请勿在垃圾场逗留"}`)) return } // Authorized if scf.Authorized && currentUser.Flag < 5 { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(`{"retcode":401,"retmsg":"Unauthorized"}`)) return } cobj.Articles = db.Zget("category_article_num", youdb.I2b(cobj.Id)).Uint64() pageInfo := model.CommentList(db, cmd, "article_comment:"+aid, key, scf.CommentListNum, scf.TimeZone, currentUser.IgnoreLimitedUsers) if currentUser.IgnoreUser != "" { for _, uid := range strings.Split(currentUser.IgnoreUser, ",") { uid, err := strconv.ParseUint(uid, 10, 64) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"type err"}`)) return } for i := 0; i < len(pageInfo.Items); i++ { if pageInfo.Items[i].Uid == uid { pageInfo.Items = append(pageInfo.Items[:i], pageInfo.Items[i+1:]...) i-- } } } } type articleForDetail struct { model.Article ContentFmt template.HTML TagStr template.HTML Name string Avatar string Views uint64 AddTimeFmt string EditTimeFmt string } type pageData struct { PageData Aobj articleForDetail Author model.User Cobj model.Category Relative model.ArticleRelative PageInfo model.CommentPageInfo Views uint64 } tpl := h.CurrentTpl(r) evn := &pageData{} evn.SiteCf = scf evn.Title = aobj.Title + " - " + cobj.Name + " - " + scf.Name evn.Keywords = aobj.Tags evn.Description = cobj.Name + " - " + aobj.Title + " - " + aobj.Tags evn.IsMobile = tpl == "mobile" evn.CurrentUser = currentUser evn.ShowSideAd = true evn.PageName = "article_detail" evn.HotNodes = model.CategoryHot(db, scf.CategoryShowNum, scf.MustLoginNodeIds) author, _ := model.UserGetById(db, aobj.Uid) viewsNum, _ := db.Hincr("article_views", youdb.I2b(aobj.Id), 1) evn.Aobj = articleForDetail{ Article: aobj, ContentFmt: template.HTML(util.ContentFmt(db, aobj.Content)), Name: author.Name, Avatar: author.Avatar, Views: viewsNum, AddTimeFmt: util.TimeFmt(aobj.AddTime, "2006-01-02", scf.TimeZone), EditTimeFmt: util.TimeFmt(aobj.EditTime, "2006-01-02", scf.TimeZone), } if len(aobj.Tags) > 0 { var tags []string for _, v := range strings.Split(aobj.Tags, ",") { tags = append(tags, `<a href="/tag/`+v+`">`+v+`</a>`) } evn.Aobj.TagStr = template.HTML(strings.Join(tags, ", ")) } evn.Cobj = cobj evn.Relative = model.ArticleGetRelative(db, aobj.Id, aobj.Tags) evn.PageInfo = pageInfo token := h.GetCookie(r, "token") if len(token) == 0 { token := xid.New().String() h.SetCookie(w, "token", token, 1) } h.Render(w, tpl, evn, "layout.html", "article.html") } func (h *BaseHandler) ArticleDetailPost(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") token := h.GetCookie(r, "token") if len(token) == 0 { w.Write([]byte(`{"retcode":400,"retmsg":"token cookie missed"}`)) return } aid := pat.Param(r, "aid") _, err := strconv.Atoi(aid) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"aid type err:` + err.Error() + `"}`)) return } type recForm struct { Act string `json:"act"` Link string `json:"link"` Content string `json:"content"` } type response struct { normalRsp Content string `json:"content"` Html template.HTML `json:"html"` } decoder := json.NewDecoder(r.Body) var rec recForm err = decoder.Decode(&rec) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"json Decode err:` + err.Error() + `"}`)) return } defer r.Body.Close() db := h.App.Db rsp := response{} if rec.Act == "link_click" { rsp.Retcode = 200 if len(rec.Link) > 0 { hash := md5.Sum([]byte(rec.Link)) urlMd5 := hex.EncodeToString(hash[:]) bn := "article_detail_token" clickKey := []byte(token + ":click:" + urlMd5) if db.Zget(bn, clickKey).State == "ok" { w.Write([]byte(`{"retcode":403,"retmsg":"err"}`)) return } db.Zset(bn, clickKey, uint64(time.Now().UTC().Unix())) db.Hincr("url_md5_click", []byte(urlMd5), 1) w.Write([]byte(`{"retcode":200,"retmsg":"ok"}`)) return } } else if rec.Act == "comment_preview" { rsp.Retcode = 200 rsp.Html = template.HTML(util.ContentFmt(db, rec.Content)) } else if rec.Act == "comment_submit" { timeStamp := uint64(time.Now().UTC().Unix()) currentUser, _ := h.CurrentUser(w, r) if currentUser.Flag < 5 { w.Write([]byte(`{"retcode":403,"retmsg":"forbidden"}`)) return } if (timeStamp - currentUser.LastReplyTime) < uint64(h.App.Cf.Site.CommentInterval) { w.Write([]byte(`{"retcode":403,"retmsg":"out off comment interval"}`)) return } aobj, err := model.ArticleGetById(db, aid) if err != nil { w.Write([]byte(`{"retcode":404,"retmsg":"not found"}`)) return } if aobj.CloseComment { w.Write([]byte(`{"retcode":403,"retmsg":"comment forbidden"}`)) return } commentId, _ := db.HnextSequence("article_comment:" + aid) scf := h.App.Cf.Site if currentUser.Flag == 99 && (strings.Contains(rec.Content, "警告一次") || strings.Contains(rec.Content, "管理员回复")) { currentUser, err = model.UserGetById(db, uint64(scf.AdminBotId)) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"json Decode err:` + err.Error() + `"}`)) return } } if currentUser.Flag >= 96 && strings.Contains(rec.Content, "匿名者说") { currentUser, err = model.UserGetById(db, uint64(scf.AnonymousBotId)) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"json Decode err:` + err.Error() + `"}`)) return } } obj := model.Comment{ Id: commentId, Aid: aobj.Id, Uid: currentUser.Id, Content: rec.Content, AddTime: timeStamp, ClientIp: "", } jb, _ := json.Marshal(obj) db.Hset("article_comment:"+aid, youdb.I2b(obj.Id), jb) // 文章评论bucket db.Hincr("count", []byte("comment_num"), 1) // 评论总数 // 用户回复文章列表 db.Zset("user_article_reply:"+strconv.FormatUint(obj.Uid, 10), youdb.I2b(obj.Aid), obj.AddTime) // 更新文章列表时间 aobj.Comments = commentId aobj.RUid = currentUser.Id aobj.EditTime = timeStamp jb2, _ := json.Marshal(aobj) db.Hset("article", youdb.I2b(aobj.Id), jb2) currentUser.LastReplyTime = timeStamp currentUser.Replies += 1 jb3, _ := json.Marshal(currentUser) db.Hset("user", youdb.I2b(currentUser.Id), jb3) // 不顶帖用户组 if currentUser.Flag != 6 { // 总文章列表 db.Zset("article_timeline", youdb.I2b(aobj.Id), timeStamp) // 分类文章列表 db.Zset("category_article_timeline:"+strconv.FormatUint(aobj.Cid, 10), youdb.I2b(aobj.Id), timeStamp) } // @ somebody in comment & topic author if aobj.Cid != 19 && aobj.Cid != 20 { sbs := util.GetMention("@"+strconv.FormatUint(aobj.Uid, 10)+" "+rec.Content, []string{currentUser.Name, strconv.FormatUint(currentUser.Id, 10)}) for _, sb := range sbs { var sbObj model.User sbu, err := strconv.ParseUint(sb, 10, 64) if err != nil { // @ user name sbObj, err = model.UserGetByName(db, strings.ToLower(sb)) } else { // @ user id sbObj, err = model.UserGetById(db, sbu) } if err == nil { if len(sbObj.Notice) > 0 { aidList := util.SliceUniqStr(strings.Split(aid+","+sbObj.Notice, ",")) if len(aidList) > 100 { aidList = aidList[:100] } sbObj.Notice = strings.Join(aidList, ",") sbObj.NoticeNum = len(aidList) } else { sbObj.Notice = aid sbObj.NoticeNum = 1 } jb, _ := json.Marshal(sbObj) db.Hset("user", youdb.I2b(sbObj.Id), jb) } } } rsp.Retcode = 200 } json.NewEncoder(w).Encode(rsp) } func (h *BaseHandler) ContentPreviewPost(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") token := h.GetCookie(r, "token") if len(token) == 0 { w.Write([]byte(`{"retcode":400,"retmsg":"token cookie missed"}`)) return } currentUser, _ := h.CurrentUser(w, r) if currentUser.Flag < 5 { w.Write([]byte(`{"retcode":403,"retmsg":"forbidden"}`)) return } type recForm struct { Act string `json:"act"` Link string `json:"link"` Content string `json:"content"` } type response struct { normalRsp Content string `json:"content"` Html template.HTML `json:"html"` } decoder := json.NewDecoder(r.Body) var rec recForm err := decoder.Decode(&rec) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"json Decode err:` + err.Error() + `"}`)) return } defer r.Body.Close() db := h.App.Db rsp := response{} if rec.Act == "preview" && len(rec.Content) > 0 { rsp.Retcode = 200 rsp.Html = template.HTML(util.ContentFmt(db, rec.Content)) } json.NewEncoder(w).Encode(rsp) } -
rss 不输出树洞、水区和垃圾场内容
@小二 #3 不知道,点了“发表”,什么反应都没有。。
算了,有空把那些代码都改了吧。我是手机,没法git clone完整的项目,所以我都是怎么改简单,怎么来的
-
rss 不输出树洞、水区和垃圾场内容
@翻车了 #1 我发不了帖子了!!!
我觉得,feed那段代码,实在不敢恭维!
feed下,走的是 ArticleFeedList
feed节点下,走的是 ArticleFeedCategoryList
我也想在ArticleFeedList里写,但是我觉得很多代码完全是重复而且冗余的
如果我来改,我是从route层就已经改掉了,后面的代码会精简很多
-
rss 不输出树洞、水区和垃圾场内容
https://github.com/Terminus2049/2049bbs/issues/7
修改代码路径 https://github.com/Terminus2049/2049bbs/blob/master/controller/feed.go
package controller import ( "net/http" "strconv" "text/template" "github.com/terminus2049/2049bbs/model" "goji.io/pat" ) func (h *BaseHandler) FeedHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/atom+xml; charset=utf-8") scf := h.App.Cf.Site var feed = `<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>` + scf.Name + `</title> <link rel="self" type="application/atom+xml" href="` + scf.MainDomain + `/feed"/> <link rel="hub" href="https://pubsubhubbub.appspot.com"/> <updated>{ {.Update} }</updated> <id>` + scf.MainDomain + `/feed</id> <author> <name>` + scf.Name + `</name> </author> { {range $_, $item := .Items} } <entry> <title>{ {$item.Title} }</title> <id>` + scf.MainDomain + `/t/{ {$item.Id} }</id> <link rel="alternate" type="text/html" href="` + scf.MainDomain + `/t/{ {$item.Id} }" /> <published>{ {$item.AddTimeFmt} }</published> <updated>{ {$item.EditTimeFmt} }</updated> <content type="text/plain"> { {$item.Cname} } - { {$item.Name} } - { {$item.Des} } </content> </entry> { {end} } </feed> ` db := h.App.Db items := model.ArticleFeedList(db, 20, h.App.Cf.Site.TimeZone) var upDate string if len(items) > 0 { upDate = items[0].AddTimeFmt } t := template.Must(template.New("feed").Parse(feed)) t.Execute(w, struct { Update string Items []model.ArticleFeedListItem }{ Update: upDate, Items: items, }) } func (h *BaseHandler) FeedCategoryHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/atom+xml; charset=utf-8") scf := h.App.Cf.Site var feed = `<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>` + scf.Name + `</title> <link rel="self" type="application/atom+xml" href="` + scf.MainDomain + `/feed"/> <link rel="hub" href="https://pubsubhubbub.appspot.com"/> <updated>{ {.Update} }</updated> <id>` + scf.MainDomain + `/feed</id> <author> <name>` + scf.Name + `</name> </author> { {range $_, $item := .Items} } <entry> <title>{ {$item.Title} }</title> <id>` + scf.MainDomain + `/t/{ {$item.Id} }</id> <link rel="alternate" type="text/html" href="` + scf.MainDomain + `/t/{ {$item.Id} }" /> <published>{ {$item.AddTimeFmt} }</published> <updated>{ {$item.EditTimeFmt} }</updated> <content type="text/plain"> { {$item.Cname} } - { {$item.Name} } - { {$item.Des} } </content> </entry> { {end} } </feed> ` cid := pat.Param(r, "cid") _, err := strconv.Atoi(cid) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"cid type err"}`)) return } if cid == 19 || cid == 20 { w.Write([]byte(`{"retcode":400,"retmsg":"cid is illeage"}`)) return } db := h.App.Db items := model.ArticleFeedCategoryList(db, cid, 20, h.App.Cf.Site.TimeZone) var upDate string if len(items) > 0 { upDate = items[0].AddTimeFmt } t := template.Must(template.New("feed").Parse(feed)) t.Execute(w, struct { Update string Items []model.ArticleFeedListItem }{ Update: upDate, Items: items, }) } -
征集antispam方案
@小二 #94 很多issue没明白你想做什么 关于@相关功能,我可以 https://github.com/Terminus2049/2049bbs/blob/master/controller/article.go 关于rss相关功能,我可以 https://github.com/Terminus2049/2049bbs/blob/master/controller/feed.go
写好了我发出来
-
征集antispam方案
@小二 #91 你说的1700威望那个人,反共反魔怔了。他经常发一些悲剧,不去同情受害人,却幸灾乐祸,觉得又是乳化,乳包的好材料。它就是一个把自己快乐建立在别人的痛苦之上的人。
这次熊熊被欺负,不是第一时间去关心熊熊身心健康。反而处处刁难Rebecca,然后泼2049脏水。
这个人灵魂都已经扭曲了。
-
征集antispam方案
如果小二有什么想实现的功能,我能帮忙实现的,我都会写好放到2049,你可以自己看看接受与否。GitHub上就不提pr了
-
征集antispam方案
@张三 #84 正常成年人都需要上班,不可能熊熊那样24小时水帖。如果你看熊熊的发帖时间和规律就能知道,绝对不可能在上班时间。她是不是女生不知道。但肯定是因为瘟疫,没上学的学生
-
征集antispam方案
@Phragmites #83 大家都对这个事情很严肃,我已经帮忙写了代码给小二参考。说的不是熊熊的事情,是你。所以你没有明白
-
2049增加Google验证码代码
@小二 #4 不知道能帮到多少忙
-
征集antispam方案
@Phragmites #78 小二的意思,你不要把事情弄得太严肃
-
2049代码记录
Lowering qubit requirements using binary codes
Introduction
Molecular Hamiltonians are known to have certain symmetries that are not taken into account by mappings like the Jordan-Wigner or Bravyi-Kitaev transform. The most notable of such symmetries is the conservation of the total number of particles in the system. Since those symmetries effectively reduce the degrees of freedom of the system, one is able to reduce the number of qubits required for simulation by utilizing binary codes (arXiv:1712.07067).
We can represent the symmetry-reduced Fermion basis by binary vectors of a set $\mathcal{V} \ni \boldsymbol{\nu}$, with $ \boldsymbol{\nu} = (\nu_0, \, \nu_1, \dots, \, \nu_{N-1} ) $, where every component $\nu_i \in \lbrace 0, 1 \rbrace $ and $N$ is the total number of Fermion modes. These binary vectors $ \boldsymbol{\nu}$ are related to the actual basis states by: $$ \left[\prod_{i=0}^{N-1} (a_i^{\dagger})^{\nu_i} \right] \left|{\text{vac}}\right\rangle \, , $$ where $ (a_i^\dagger)^{0}=1$. The qubit basis, on the other hand, can be characterized by length-$n$ binary vectors $\boldsymbol{\omega}=(\omega_0, \, \dots , \, \omega_{n-1})$, that represent an $n$-qubit basis state by: $$ \left|{\omega_0}\right\rangle \otimes \left|\omega_1\right\rangle \otimes \dots \otimes \left|{\omega_{n-1}}\right\rangle \, . $$ Since $\mathcal{V}$ is a mere subset of the $N$-fold binary space, but the set of the vectors $\boldsymbol{\omega}$ spans the entire $n$-fold binary space we can assign every vector $\boldsymbol{\nu}$ to a vector $ \boldsymbol{\omega}$, such that $n<N$. This reduces the amount of qubits required by $(N-n)$. The mapping can be done by a binary code, a classical object that consists of an encoder function $\boldsymbol{e}$ and a decoder function $\boldsymbol{d}$. These functions relate the binary vectors $\boldsymbol{e}(\boldsymbol{\nu})=\boldsymbol{\omega}$, $\boldsymbol{d}(\boldsymbol{\omega})=\boldsymbol{\nu}$, such that $\boldsymbol{d}(\boldsymbol{e}(\boldsymbol{\nu}))=\boldsymbol{\nu}$. In OpenFermion, we, at the moment, allow for non-linear decoders $\boldsymbol{d}$ and linear encoders $\boldsymbol{e}(\boldsymbol{\nu})=A \boldsymbol{\nu}$, where the matrix multiplication with the $(n\times N)$-binary matrix $A$ is $(\text{mod 2})$ in every component.
Symbolic binary functions
The non-linear binary functions for the components of the decoder are here modeled by the $\text{BinaryPolynomial}$ class in openfermion.ops. For initialization we can conveniently use strings ('w0 w1 + w1 +1' for the binary function $\boldsymbol{\omega} \to \omega_0 \omega_1 + \omega_1 + 1 \;\text{mod 2}$), the native data structure or symbolic addition and multiplication.
-
2049代码记录
这里没法排版,看这里好了
https://nbviewer.jupyter.org/github/quantumlib/OpenFermion/blob/master/examples/jordan_wigner_and_bravyi_kitaev_transforms.ipynb
-
2049代码记录
狄拉克符号 打不出来!!!! 全乱码了!!!
神奇了,矩阵伪逆符号居然显示是正确的,这个markdown编辑器功能真的是缩水啊
-
2049代码记录
https://zhuanlan.zhihu.com/p/47681576
https://zhuanlan.zhihu.com/p/47682212
-
2049代码记录
Q4 表示 分母是 2的4次方。同理 Q10 表示 分母是 2的10次方。
以下是数学推导过程 10 * log10("true energy") in Q4 = 2^4 * 10 * log10("true energy")
= 160 * log10(2) * log2("true energy")
令 true energy = |energy| * 2^|tot_rshifts| 且 |kLogConst| = 160 * log10(2)
160 * log10(2) * log2("true energy") = |kLogConst| * log2(|energy| * 2^|tot_rshifts|)
= |kLogConst| * (log2(|energy|) + |tot_rshifts|)
令 |energy| = 2^14 + frac_Q15
|kLogConst| * (log2(|energy|) + |tot_rshifts|) = |kLogConst| * (log2(2^14 + frac_Q15 ) + |tot_rshifts|)
= |kLogConst| * (log2(2^14 (1+ frac_Q15>>14) ) + |tot_rshifts|)
= |kLogConst| * (14 + log2(1+ frac_Q15>>14) + |tot_rshifts|)
~= |kLogConst| * (14 + frac_Q15>>14 + |tot_rshifts|)
令 frac_Q15 = (|energy| & 0x00003FFF)
int16_t log2_energy = kLogEnergyIntPart;
log2_energy += (int16_t) ((energy & 0x00003FFF) >> 4);
*log_energy = (int16_t)(((kLogConst * log2_energy) >> 19) +
((tot_rshifts * kLogConst) >> 9)); -
2049代码记录
高通滤波和低通滤波明天记录下
-
2049增加Google验证码代码
修改代码 https://github.com/Terminus2049/2049bbs/blob/df0914d35b4be3ccf6ae1e8da525b355dd54bd01/controller/user.go
登录的时候,访问 UserLogin 函数 修改如下
func (h *BaseHandler) UserLogin(w http.ResponseWriter, r *http.Request) { type pageData struct { PageData Act string Token string CaptchaId string } act := strings.TrimLeft(r.RequestURI, "/") title := "登录" if act == "register" { title = "注册" } tpl := h.CurrentTpl(r) evn := &pageData{} evn.SiteCf = h.App.Cf.Site evn.Title = title evn.Keywords = "" evn.Description = "" evn.IsMobile = tpl == "mobile" evn.ShowSideAd = true evn.PageName = "user_login_register" evn.Act = act token := h.GetCookie(r, "token") if len(token) == 0 { token := xid.New().String() h.SetCookie(w, "token", token, 1) } h.Render(w, tpl, evn, "layout.html", "userlogin.html") }提交代码修改如下
func (h *BaseHandler) UserLoginPost(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") token := h.GetCookie(r, "token") if len(token) == 0 { w.Write([]byte(`{"retcode":400,"retmsg":"token cookie missed"}`)) return } act := strings.TrimLeft(r.RequestURI, "/") type recForm struct { Name string `json:"name"` Password string `json:"password"` Response string `json:"g-recaptcha-response"` } type response struct { normalRsp } decoder := json.NewDecoder(r.Body) var rec recForm err := decoder.Decode(&rec) if err != nil { w.Write([]byte(`{"retcode":400,"retmsg":"json Decode err:` + err.Error() + `"}`)) return } defer r.Body.Close() if len(rec.Name) == 0 || len(rec.Password) == 0 { w.Write([]byte(`{"retcode":400,"retmsg":"name or pw is empty"}`)) return } nameLow := strings.ToLower(rec.Name) if !util.IsUserName(nameLow) { w.Write([]byte(`{"retcode":400,"retmsg":"name fmt err"}`)) return } // did we get a proper recaptcha response? if null, redirect back to sigup page if rec.Response == "" { // user press submit button without passing reCAPTCHA test // abort http.Redirect(w, r, "/", 301) return // return control to stop execution, otherwise it will continue } // get end user's IP address remoteip, _, _ := net.SplitHostPort(r.RemoteAddr) fmt.Println("remote ip : ", remoteip) // to verify if the recaptcha is REAL. we must send // secret + response + remoteip(optional) to postURL secret := "[你的 secret key]" postURL := "https://www.google.com/recaptcha/api/siteverify" postStr := url.Values{"secret": {secret}, "response": {rec.Response}, "remoteip": {remoteip}} responsePost, err := http.PostForm(postURL, postStr) if err != nil { fmt.Println(err) return } defer responsePost.Body.Close() body, err := ioutil.ReadAll(responsePost.Body) if err != nil { fmt.Println(err) return } // this part is for server side verification var APIResp JSONAPIResponse json.Unmarshal(body, &APIResp) fmt.Println(APIResp) db := h.App.Db timeStamp := uint64(time.Now().UTC().Unix()) if act == "login" { bn := "user_login_token" key := []byte(token + ":loginerr") if db.Zget(bn, key).State == "ok" { // todo //w.Write([]byte(`{"retcode":400,"retmsg":"name and pw not match"}`)) //return } uobj, err := model.UserGetByName(db, nameLow) if err != nil { w.Write([]byte(`{"retcode":405,"retmsg":"json Decode err:` + err.Error() + `","newCaptchaId":"` + captcha.New() + `"}`)) return } if uobj.Password != rec.Password { db.Zset(bn, key, uint64(time.Now().UTC().Unix())) w.Write([]byte(`{"retcode":405,"retmsg":"name and pw not match","newCaptchaId":"` + captcha.New() + `"}`)) return } sessionid := xid.New().String() uobj.LastLoginTime = timeStamp uobj.Session = sessionid jb, _ := json.Marshal(uobj) db.Hset("user", youdb.I2b(uobj.Id), jb) h.SetCookie(w, "SessionID", strconv.FormatUint(uobj.Id, 10)+":"+sessionid, 365) } else { // register siteCf := h.App.Cf.Site if siteCf.CloseReg { w.Write([]byte(`{"retcode":400,"retmsg":"stop to new register"}`)) return } if db.Hget("user_name2uid", []byte(nameLow)).State == "ok" { w.Write([]byte(`{"retcode":405,"retmsg":"name is exist","newCaptchaId":"` + captcha.New() + `"}`)) return } userId, _ := db.HnextSequence("user") flag := 5 if siteCf.RegReview { flag = 1 } if userId == 1 { flag = 99 } uobj := model.User{ Id: userId, Name: rec.Name, Password: rec.Password, Flag: flag, RegTime: timeStamp, LastLoginTime: timeStamp, Session: xid.New().String(), } // 从指定的用户中随机选一个头像作为新注册用户头像 // 指定用户必须连续,取最小id和最大id rand.Seed(time.Now().UnixNano()) min := siteCf.AvatarMinId // 2539 max := siteCf.AvatarMaxId // 2558 sampleID := rand.Intn(max-min+1) + min uidStr := strconv.FormatUint(uint64(sampleID), 10) uobj.Avatar = uidStr uobj.IgnoreLimitedUsers = true jb, _ := json.Marshal(uobj) db.Hset("user", youdb.I2b(uobj.Id), jb) db.Hset("user_name2uid", []byte(nameLow), youdb.I2b(userId)) db.Hset("user_flag:"+strconv.Itoa(flag), youdb.I2b(uobj.Id), []byte("")) h.SetCookie(w, "SessionID", strconv.FormatUint(uobj.Id, 10)+":"+uobj.Session, 365) } h.DelCookie(w, "token") rsp := response{} rsp.Retcode = 200 json.NewEncoder(w).Encode(rsp) } -
2049增加Google验证码代码
安全可靠,小二可以自己比对下我的修改 @小二 如果有任何问题,都可以@我
-
2049增加Google验证码代码
额,忘了几个地方
前端html 增加
<script src='https://www.google.com/recaptcha/api.js'></script>后端golang部分
type JSONAPIResponse struct { Success bool `json:"success"` ChallengeTS time.Time `json:"challenge_ts"` // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ) Hostname string `json:"hostname"` // the hostname of the site where the reCAPTCHA was solved ErrorCodes []int `json:"error-codes"` //optional }增加
json.Unmarshal(body, &APIResp) fmt.Println(APIResp)增加判断APIResp.Success 是true还是false 的代码就可以了
-
2049增加Google验证码代码
参考文章 https://www.socketloop.com/tutorials/golang-recaptcha-example
1.去这里 http://www.google.com/recaptcha/ 申请secret key
2.修改代码
https://github.com/Terminus2049/2049bbs/blob/master/view/default/desktop/userlogin.html <p><label>验证码: <input type="text" id="captchaSolution" class="sl w200" value="" /></label></p>改为
<p><label>验证码: <div class="g-recaptcha" data-sitekey="[第一步申请的secret key]"></div></label></p>另外 修改 form_post 函数
function form_post(){ var name = $('#name').val(); var password = $('#password').val(); var password2 = $('#password2').val(); var g-recaptcha-response= $('#g-recaptcha-response').val(); if(name && password && g-recaptcha-response){ if(password && password2) { if(password != password2){ $.toast('密码两次输入不同'); $('#password').val(''); $('#password2').val(''); return false; } } $.ajax({ type: "POST", url: "/{ {.Act} }", data: JSON.stringify({'act': '{ {.Act} }', 'name': name, 'password': md5(password), 'g-recaptcha-response': g-recaptcha-response}), dataType: "json", success: function(data){ if(data.retcode==200){ window.location.href = "/"; }else{ reload(); $.toast(data.retmsg); } }, fail: function(errMsg) { $.toast(errMsg); } }); }else{ $.toast('用户名、密码和验证码必填'); } return false; }mobile版本,参考desktop继续修改 https://github.com/Terminus2049/2049bbs/blob/master/view/default/mobile/userlogin.html
-
征集antispam方案
@Shiro #55 标准HTTP就不带Mac地址,而且这个不是唯一可以伪造。还违背了匿名承诺
-
征集antispam方案
@hello _chris #52 https://www.socketloop.com/tutorials/golang-recaptcha-example
我觉得这个说的很清楚,晚上我改个demo发出来,我觉得小二自己可以搞定的
-
致管理员
不觉得敏感词就一定是政治审核。隔壁有些人,他们就是来树洞参观的,从不发帖子,你让他们注册写什么,自我介绍么?
如果小二觉得人少,人肉审核可以接受,那我觉得对注册方而言,要等很久才可能知道自己注册成功了,可能就没意思了,谁注册不是一时兴起呢?
-
征集antispam方案
我觉得品葱管理员不应该干涉2049内政,如果参与讨论应该以2049用户身份。
应该使用敏感词系统,YouTube也有黄标,这个是正常网站运营的正常手段。可以根据各个时期增加删除。不应该因为共产党用了这个技术就排斥这个技术。
共产党控制下也有医院,难道医院就是邪恶的么?
技术不存在正邪之分,完全取决于怎么用和为什么用?
小号属于合法行使自己的言论自由,不应该因为是小号被禁,而应该取决于言论是不是符合2049的理性讨论注册申明。
-
总统应该取消两届八年的任期限制
@陈士杰 #16 我在11楼表达了我的理解,管理国家的是一个团体。这个团体不一定叫党。比如朱元璋成立明朝。他没有管自己那个团体叫党,但他代表了那个利益集团。我觉得只是现代化社会,人类社团组织形式得到了进化,党成为了现代化政治的标准
-
话说,国内现在网文感觉没以前有活力了,怎么回事?
Google搜中文都已经是垃圾了,应该说中文已经被污染了。不止网文
-
biteinside是品葱站长不是小二
@BE4 #5 好吧