// 更新该项目的喜欢数 // objid:被喜欢对象id;num: 喜欢数(负数表示取消喜欢) func (self ProjectLike) UpdateLike(objid, num int) { // 更新喜欢数(TODO:暂时每次都更新表) err := model.NewOpenProject().Where("id=?", objid).Increment("likenum", num) if err != nil { logger.Errorln("更新项目喜欢数失败:", err) } }
// 开源项目总数 func ProjectsTotal() (total int) { total, err := model.NewOpenProject().Count() if err != nil { logger.Errorln("project service ProjectsTotal error:", err) } return }
func UpdateProjectStatus(id, status int, username string) error { if status < model.StatusNew || status > model.StatusOffline { return errors.New("status is illegal") } logger.Infoln("UpdateProjectStatus by username:"******"status=?", status).Where("id=?", id).Update() }
// 更新该项目的评论信息 // cid:评论id;objid:被评论对象id;uid:评论者;cmttime:评论时间 func (self ProjectComment) UpdateComment(cid, objid, uid int, cmttime string) { id := strconv.Itoa(objid) // 更新评论数(TODO:暂时每次都更新表) err := model.NewOpenProject().Where("id="+id).Increment("cmtnum", 1) if err != nil { logger.Errorln("更新项目评论数失败:", err) } }
// 获得某个用户最近发布的开源项目 func FindUserRecentProjects(username string) []*model.OpenProject { projectList, err := model.NewOpenProject().Where("username=?", username).Limit("0,5").Order("ctime DESC").FindAll() if err != nil { logger.Errorln("project service FindUserRecentProjects error:", err) return nil } return projectList }
// 通过objid获得 project 的所有者 func getProjectOwner(id int) int { project := model.NewOpenProject() err := project.Where("id=" + strconv.Itoa(id)).Find() if err != nil { logger.Errorln("project service getProjectOwner Error:", err) return 0 } user := FindUserByUsername(project.Username) return user.Uid }
// 获取多个项目详细信息 func FindProjectsByIds(ids []int) []*model.OpenProject { if len(ids) == 0 { return nil } inIds := util.Join(ids, ",") projects, err := model.NewOpenProject().Where("id in(" + inIds + ")").FindAll() if err != nil { logger.Errorln("project service FindProjectsByIds error:", err) return nil } return projects }
func ProjectUriExists(uri string) bool { project := model.NewOpenProject() err := project.Where("uri=?", uri).Find("id") if err != nil { return false } if project.Id > 0 { return true } return false }
// flush 将浏览数刷入数据库中 func (this *view) flush() { this.locker.Lock() defer this.locker.Unlock() objid := strconv.Itoa(this.objid) switch this.objtype { case model.TYPE_TOPIC: model.NewTopicEx().Where("tid="+objid).Increment("view", this.num) case model.TYPE_ARTICLE: model.NewArticle().Where("id="+objid).Increment("viewnum", this.num) case model.TYPE_RESOURCE: model.NewResourceEx().Where("id="+objid).Increment("viewnum", this.num) case model.TYPE_PROJECT: model.NewOpenProject().Where("id="+objid).Increment("viewnum", this.num) } this.num = 0 }
// 新建项目 // uri: /project/new{json:(|.json)} func NewProjectHandler(rw http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) name := req.PostFormValue("name") // 请求新建项目页面 if name == "" || req.Method != "POST" || vars["json"] == "" { project := model.NewOpenProject() req.Form.Set(filter.CONTENT_TPL_KEY, "/template/projects/new.html") filter.SetData(req, map[string]interface{}{"project": project, "activeProjects": "active"}) return } user, _ := filter.CurrentUser(req) err := service.PublishProject(user, req.PostForm) if err != nil { fmt.Fprint(rw, `{"ok": 0, "error":"内部服务错误!"}`) return } fmt.Fprint(rw, `{"ok": 1, "data":""}`) }
// 获取开源项目列表(分页) func FindProjects(lastId, limit string) []*model.OpenProject { project := model.NewOpenProject() query := "status IN(?,?)" args := []interface{}{model.StatusNew, model.StatusOnline} if lastId != "0" { query += " AND id<?" args = append(args, lastId) } projectList, err := project.Where(query, args...).Order("id DESC").Limit(limit). FindAll() if err != nil { logger.Errorln("project service FindProjects Error:", err) return nil } return projectList }
// 获取单个项目 func FindProject(uniq string) *model.OpenProject { field := "id" _, err := strconv.Atoi(uniq) if err != nil { field = "uri" } project := model.NewOpenProject() err = project.Where(field+"=? AND status IN(?,?)", uniq, model.StatusNew, model.StatusOnline).Find() if err != nil { logger.Errorln("project service FindProject error:", err) return nil } if project.Id == 0 { return nil } return project }
// 获取开源项目列表(分页,后台用) func FindProjectByPage(conds map[string]string, curPage, limit int) ([]*model.OpenProject, int) { conditions := make([]string, 0, len(conds)) for k, v := range conds { conditions = append(conditions, k+"="+v) } project := model.NewOpenProject() limitStr := strconv.Itoa((curPage-1)*limit) + "," + strconv.Itoa(limit) projectList, err := project.Where(strings.Join(conditions, " AND ")).Order("id DESC").Limit(limitStr). FindAll() if err != nil { logger.Errorln("project service FindProjectByPage Error:", err) return nil, 0 } total, err := project.Count() if err != nil { logger.Errorln("project service FindProjectByPage COUNT Error:", err) return nil, 0 } return projectList, total }
func GenSitemap() { sitemapFiles := []string{} // 首页 home := map[string]string{ "loc": "http://" + config.Config["domain"], "lastmode": time.Now().Format(time.RFC3339), } var ( little = 1 step = 4999 large = little + step ) // 文章 article := model.NewArticle() for { sitemapFile := "sitemap_article_" + strconv.Itoa(large) + ".xml" articles, err := article.Where("id BETWEEN ? AND ? AND status!=?", little, large, model.StatusOffline).FindAll("id", "mtime") little = large + 1 large = little + step if err != nil { continue } if len(articles) == 0 { break } data := map[string]interface{}{ "home": home, "articles": articles, } if err = output(sitemapFile, data); err == nil { sitemapFiles = append(sitemapFiles, sitemapFile) } } little = 1 large = little + step // 主题(帖子) topic := model.NewTopic() for { sitemapFile := "sitemap_topic_" + strconv.Itoa(large) + ".xml" topics, err := topic.Where("tid BETWEEN ? AND ? AND flag IN(?,?)", little, large, 0, 1).FindAll("tid", "mtime") little, large = large+1, little+step if err != nil { continue } if len(topics) == 0 { break } data := map[string]interface{}{ "home": home, "topics": topics, } if err = output(sitemapFile, data); err == nil { sitemapFiles = append(sitemapFiles, sitemapFile) } } little = 1 large = little + step // 资源 resource := model.NewResource() for { sitemapFile := "sitemap_resource_" + strconv.Itoa(large) + ".xml" resources, err := resource.Where("id BETWEEN ? AND ?", little, large).FindAll("id", "mtime") little, large = large+1, little+step if err != nil { continue } if len(resources) == 0 { break } data := map[string]interface{}{ "home": home, "resources": resources, } if err = output(sitemapFile, data); err == nil { sitemapFiles = append(sitemapFiles, sitemapFile) } } little = 1 large = little + step // 项目 project := model.NewOpenProject() for { sitemapFile := "sitemap_project_" + strconv.Itoa(large) + ".xml" projects, err := project.Where("id BETWEEN ? AND ? AND status=?", little, large, model.StatusOnline).FindAll("id", "uri", "mtime") little, large = large+1, little+step if err != nil { continue } if len(projects) == 0 { break } data := map[string]interface{}{ "home": home, "projects": projects, } if err = output(sitemapFile, data); err == nil { sitemapFiles = append(sitemapFiles, sitemapFile) } } little = 1 large = little + step // wiki wiki := model.NewWiki() for { sitemapFile := "sitemap_wiki_" + strconv.Itoa(large) + ".xml" wikis, err := wiki.Where("id BETWEEN ? AND ?", little, large).FindAll("id", "uri", "mtime") little, large = large+1, little+step if err != nil { continue } if len(wikis) == 0 { break } data := map[string]interface{}{ "home": home, "wikis": wikis, } if err = output(sitemapFile, data); err == nil { sitemapFiles = append(sitemapFiles, sitemapFile) } } file, err := os.Create(sitemapPath + "sitemapindex.xml") if err != nil { logger.Errorln("gen sitemap index file error:", err) return } defer file.Close() err = sitemapIndexTpl.Execute(file, map[string]interface{}{ "home": home, "sitemapFiles": sitemapFiles, }) if err != nil { logger.Errorln("execute sitemap index template error:", err) } }
func PublishProject(user map[string]interface{}, form url.Values) (err error) { id := form.Get("id") isModify := id != "" if !isModify && ProjectUriExists(form.Get("uri")) { err = errors.New("uri存在") return } username := user["username"].(string) project := model.NewOpenProject() if isModify { err = project.Where("id=?", id).Find() if err != nil { logger.Errorln("Publish Project find error:", err) return } isAdmin := false if _, ok := user["isadmin"]; ok { isAdmin = user["isadmin"].(bool) } if project.Username != username && !isAdmin { err = NotModifyAuthorityErr return } util.ConvertAssign(project, form) } else { util.ConvertAssign(project, form) project.Username = username project.Ctime = util.TimeNow() } project.Uri = strings.ToLower(project.Uri) github := "github.com" pos := strings.Index(project.Src, github) if pos != -1 { project.Repo = project.Src[pos+len(github)+1:] } if !isModify { _, err = project.Insert() } else { err = project.Persist(project) } if err != nil { logger.Errorln("Publish Project error:", err) } // 发布項目,活跃度+10 if uid, ok := user["uid"].(int); ok { weight := 10 if isModify { weight = 2 } go IncUserWeight("uid="+strconv.Itoa(uid), weight) } return }
// ParseOneProject 处理单个 project func ParseOneProject(projectUrl string) error { if !strings.HasPrefix(projectUrl, "http") { projectUrl = OsChinaDomain + projectUrl } var ( doc *goquery.Document err error ) // 加上 ?fromerr=xfwefs,否则页面有 js 重定向 if doc, err = goquery.NewDocument(projectUrl + "?fromerr=xfwefs"); err != nil { return errors.New("goquery fetch " + projectUrl + " error:" + err.Error()) } // 标题 category := strings.TrimSpace(doc.Find(".Project .name").Text()) name := strings.TrimSpace(doc.Find(".Project .name u").Text()) if category == "" && name == "" { return errors.New("projectUrl:" + projectUrl + " category and name are empty") } tmpIndex := strings.LastIndex(category, name) if tmpIndex != -1 { category = category[:tmpIndex] } // uri uri := projectUrl[strings.LastIndex(projectUrl, "/")+1:] project := model.NewOpenProject() err = project.Where("uri=?", uri).Find("id") // 已经存在 if project.Id != 0 { return errors.New("url" + projectUrl + "has exists!") } logoSelection := doc.Find(".Project .PN img") if logoSelection.AttrOr("title", "") != "" { project.Logo = logoSelection.AttrOr("src", "") if !strings.HasPrefix(project.Logo, "http") { project.Logo = OsChinaDomain + project.Logo } project.Logo, err = UploadUrlFile(project.Logo, ProjectLogoPrefix) if err != nil { logger.Errorln("project logo upload error:", err) } } // 获取项目相关链接 doc.Find("#Body .urls li").Each(func(i int, liSelection *goquery.Selection) { aSelection := liSelection.Find("a") uri := util.FetchRealUrl(OsChinaDomain + aSelection.AttrOr("href", "")) switch aSelection.Text() { case "软件首页": project.Home = uri case "软件文档": project.Doc = uri case "软件下载": project.Download = uri } }) ctime := util.TimeNow() doc.Find("#Body .attrs li").Each(func(i int, liSelection *goquery.Selection) { aSelection := liSelection.Find("a") txt := aSelection.Text() if i == 0 { project.Licence = txt if txt == "未知" { project.Licence = "其他" } } else if i == 1 { project.Lang = txt } else if i == 2 { project.Os = txt } else if i == 3 { dtime, err := time.ParseInLocation("2006年01月02日", aSelection.Last().Text(), time.Local) if err != nil { logger.Errorln("parse ctime error:", err) } else { ctime = dtime.Local().Format("2006-01-02 15:04:05") } } }) project.Name = name project.Category = category project.Uri = uri project.Repo = strings.TrimSpace(doc.Find("#Body .github-widget").AttrOr("data-repo", "")) project.Src = "https://github.com/" + project.Repo pos := strings.Index(project.Repo, "/") if pos > -1 { project.Author = project.Repo[:pos] } else { project.Author = "网友" } if project.Doc == "" { // TODO:暂时认为一定是 Go 语言 project.Doc = "https://godoc.org/" + project.Src[8:] } desc := "" doc.Find("#Body .detail").Find("p").NextAll().Each(func(i int, domSelection *goquery.Selection) { doc.FindSelection(domSelection).WrapHtml(`<div id="tmp` + strconv.Itoa(i) + `"></div>`) domHtml, _ := doc.Find("#tmp" + strconv.Itoa(i)).Html() if domSelection.Is("pre") { desc += domHtml + "\n\n" } else { desc += html2md.Convert(domHtml) + "\n\n" } }) project.Desc = strings.TrimSpace(desc) project.Username = PresetUsernames[rand.Intn(4)] project.Status = model.ProjectStatusOnline project.Ctime = ctime _, err = project.Insert() if err != nil { return errors.New("insert into open project error:" + err.Error()) } return nil }