// 获得资源详细信息 func FindResource(id string) (resourceMap map[string]interface{}, comments []map[string]interface{}) { condition := "id=" + id resource := model.NewResource() err := resource.Where(condition).Find() if err != nil { logger.Errorln("resource service FindResource error:", err) return } resourceMap = make(map[string]interface{}) util.Struct2Map(resourceMap, resource) resourceMap["catname"] = GetCategoryName(resource.Catid) // 链接的host if resource.Form == model.LinkForm { urlObj, err := url.Parse(resource.Url) if err == nil { resourceMap["host"] = urlObj.Host } } else { resourceMap["url"] = "/resources/" + strconv.Itoa(resource.Id) } resourceEx := model.NewResourceEx() err = resourceEx.Where(condition).Find() if err != nil { logger.Errorln("resource service FindResource Error:", err) return } util.Struct2Map(resourceMap, resourceEx) // 评论信息 comments, ownerUser, _ := FindObjComments(id, strconv.Itoa(model.TYPE_RESOURCE), resource.Uid, 0) resourceMap["user"] = ownerUser return }
// 增加资源 func PublishResource(uid int, form url.Values) bool { resource := model.NewResource() err := util.ConvertAssign(resource, form) if err != nil { logger.Errorln("user ConvertAssign error", err) return false } resource.Ctime = time.Now().Format("2006-01-02 15:04:05") resource.Uid = uid id, err := resource.Insert() if err != nil { logger.Errorln("PublishResource error:", err) return false } // 发布资源,活跃度+10 go IncUserWeight("uid="+strconv.Itoa(uid), 10) // 入扩展表 resourceEx := model.NewResourceEx() resourceEx.Id = int(id) if _, err := resourceEx.Insert(); err != nil { logger.Errorln("PublishResource Ex error:", err) return false } return true }
// 资源总数 func ResourcesTotal() (total int) { total, err := model.NewResource().Count() if err != nil { logger.Errorln("resource service ResourcesTotal error:", err) } return }
// 索引资源 func IndexingResource(isAll bool) { solrClient := NewSolrClient() resourceObj := model.NewResource() resourceExObj := model.NewResourceEx() limit := strconv.Itoa(MaxRows) if isAll { id := 0 for { resourceList, err := resourceObj.Where("id>?", id).Limit(limit).FindAll() if err != nil { logger.Errorln("IndexingResource error:", err) break } if len(resourceList) == 0 { break } ids := util.Models2Intslice(resourceList, "Id") tmpStr := strings.Repeat("?,", len(ids)) query := "id in(" + tmpStr[:len(tmpStr)-1] + ")" args := make([]interface{}, len(ids)) for i, rid := range ids { args[i] = rid } resourceExList, err := resourceExObj.Where(query, args...).FindAll() if err != nil { logger.Errorln("IndexingResource error:", err) break } resourceExMap := make(map[int]*model.ResourceEx, len(resourceExList)) for _, resourceEx := range resourceExList { resourceExMap[resourceEx.Id] = resourceEx } for _, resource := range resourceList { if id < resource.Id { id = resource.Id } resourceEx, _ := resourceExMap[resource.Id] document := model.NewDocument(resource, resourceEx) addCommand := model.NewDefaultArgsAddCommand(document) solrClient.Push(addCommand) } solrClient.Post() } } }
// 获得某个用户最近的资源 func FindUserRecentResources(uid int) []*model.Resource { resourceList, err := model.NewResource().Where("uid=?", uid).Limit("0,5").Order("mtime DESC").FindAll() if err != nil { logger.Errorln("resource service FindUserRecentResources error:", err) return nil } return resourceList }
// 通过id获得资源的所有者 func getResourceOwner(id int) int { resource := model.NewResource() err := resource.Where("id=" + strconv.Itoa(id)).Find() if err != nil { logger.Errorln("resource service getResourceOwner Error:", err) return 0 } return resource.Uid }
// 获取单个 Resource 信息(用于编辑) func FindResourceById(id string) *model.Resource { resource := model.NewResource() err := resource.Where("id=?", id).Find() if err != nil { logger.Errorf("FindResourceById [%s] error:%s\n", id, err) } return resource }
// 获取多个资源详细信息 func FindResourcesByIds(ids []int) []*model.Resource { if len(ids) == 0 { return nil } inIds := util.Join(ids, ",") resources, err := model.NewResource().Where("id in(" + inIds + ")").FindAll() if err != nil { logger.Errorln("resource service FindResourcesByIds error:", err) return nil } return resources }
// 获取资源列表(分页) func FindResources(lastId, limit string) []*model.Resource { resource := model.NewResource() resourceList, err := resource.Where("id>" + lastId).Order("id DESC").Limit(limit). FindAll() if err != nil { logger.Errorln("resource service FindResources Error:", err) return nil } return resourceList }
// 获得某个分类的资源列表 func FindResourcesByCatid(catid string) []map[string]interface{} { resourceList, err := model.NewResource().Where("catid=" + catid).Order("mtime DESC").FindAll() if err != nil { logger.Errorln("resource service FindResourcesByCatid error:", err) return nil } count := len(resourceList) ids := make([]int, count) uids := make(map[int]int) for i, resource := range resourceList { ids[i] = resource.Id uids[resource.Uid] = resource.Uid } // 获取扩展信息(计数) resourceExList, err := model.NewResourceEx().Where("id in(" + util.Join(ids, ",") + ")").FindAll() if err != nil { logger.Errorln("resource service FindResourcesByCatid Error:", err) return nil } resourceExMap := make(map[int]*model.ResourceEx, len(resourceExList)) for _, resourceEx := range resourceExList { resourceExMap[resourceEx.Id] = resourceEx } userMap := getUserInfos(uids) resources := make([]map[string]interface{}, count) for i, resource := range resourceList { tmpMap := make(map[string]interface{}) util.Struct2Map(tmpMap, resource) util.Struct2Map(tmpMap, resourceExMap[resource.Id]) tmpMap["user"] = userMap[resource.Uid] // 链接的host if resource.Form == model.LinkForm { urlObj, err := url.Parse(resource.Url) if err == nil { tmpMap["host"] = urlObj.Host } } else { tmpMap["url"] = "/resources/" + strconv.Itoa(resource.Id) } resources[i] = tmpMap } return resources }
// 获得最新资源 func FindRecentResources() []map[string]interface{} { resourceList, err := model.NewResource().Limit("0,10").Order("mtime DESC").FindAll() if err != nil { logger.Errorln("resource service FindRecentResources error:", err) return nil } uids := util.Models2Intslice(resourceList, "Uid") userMap := GetUserInfos(uids) count := len(resourceList) resources := make([]map[string]interface{}, count) for i, resource := range resourceList { tmpMap := make(map[string]interface{}) util.Struct2Map(tmpMap, resource) tmpMap["user"] = userMap[resource.Uid] resources[i] = tmpMap } return resources }
// 处理 Reddit 中的一条资源 func dealRedditOneResource(contentSelection *goquery.Selection) error { aSelection := contentSelection.Find(".title a.title") title := aSelection.Text() if title == "" { return errors.New("title is empty") } resourceUrl, ok := aSelection.Attr("href") if !ok || resourceUrl == "" { return errors.New("resource url is empty") } isReddit := false resource := model.NewResource() // Reddit 自身的内容 if contentSelection.HasClass("self") { isReddit = true resourceUrl = Reddit + resourceUrl } err := resource.Where("url=?", resourceUrl).Find("id") // 已经存在 if resource.Id != 0 { // 如果是 reddit 本身的,可以更新评论信息 if !isReddit { return errors.New("url" + resourceUrl + "has exists!") } } if isReddit { resource.Form = model.ContentForm var doc *goquery.Document if doc, err = goquery.NewDocument(resourceUrl); err != nil { return errors.New("goquery reddit.com/r/golang self newdocument error:" + err.Error()) } content, err := doc.Find("#siteTable .usertext .md").Html() if err != nil { return err } doc.Find(".commentarea .comment .usertext .md").Each(func(i int, contentSel *goquery.Selection) { if i == 0 { content += `<hr/>**评论:**<br/><br/>` } comment, err := contentSel.Html() if err != nil { return } comment = strings.TrimSpace(comment) comment = resourceRe.ReplaceAllLiteralString(comment, "\n") author := contentSel.ParentsFiltered(".usertext").Prev().Find(".author").Text() content += author + ": <pre>" + comment + "</pre>" }) if strings.TrimSpace(content) == "" { return errors.New("goquery reddit.com/r/golang self newdocument(" + resourceUrl + ") error: content is empty") } resource.Content = content // reddit 本身的,当做其他资源 resource.Catid = 4 } else { resource.Form = model.LinkForm // Github,是开源项目 if contentSelection.Find(".title .domain a").Text() == "github.com" { resource.Catid = 2 } else { resource.Catid = 1 } } resource.Title = title resource.Url = resourceUrl resource.Uid = PresetUids[rand.Intn(4)] ctime := util.TimeNow() datetime, ok := contentSelection.Find(".tagline time").Attr("datetime") if ok { dtime, err := time.ParseInLocation(time.RFC3339, datetime, time.UTC) if err != nil { logger.Errorln("parse ctime error:", err) } else { ctime = dtime.Local().Format("2006-01-02 15:04:05") } } resource.Ctime = ctime if resource.Id == 0 { var id int64 id, err = resource.Insert() if err != nil { return errors.New("insert into Resource error:" + err.Error()) } // 存扩展信息 resourceEx := model.NewResourceEx() resourceEx.Id = int(id) if _, err = resourceEx.Insert(); err != nil { return errors.New("insert into ResourceEx error:" + err.Error()) } } else { if err = resource.Persist(resource); err != nil { return errors.New("persist resource:" + strconv.Itoa(resource.Id) + " error:" + err.Error()) } } return nil }
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 PublishResource(user map[string]interface{}, form url.Values) (err error) { uid := user["uid"].(int) resource := model.NewResource() if form.Get("id") != "" { err = resource.Where("id=?", form.Get("id")).Find() if err != nil { logger.Errorln("Publish Resource find error:", err) return } isAdmin := false if _, ok := user["isadmin"]; ok { isAdmin = user["isadmin"].(bool) } if resource.Uid != uid && !isAdmin { err = NotModifyAuthorityErr return } fields := []string{"title", "catid", "form", "url", "content"} if form.Get("form") == model.LinkForm { form.Set("content", "") } else { form.Set("url", "") } id := form.Get("id") query, args := updateSetClause(form, fields) err = resource.Set(query, args...).Where("id=?", id).Update() if err != nil { logger.Errorf("更新資源 【%s】 信息失败:%s\n", id, err) return } // 修改資源,活跃度+2 go IncUserWeight("uid="+strconv.Itoa(uid), 2) } else { util.ConvertAssign(resource, form) resource.Uid = uid resource.Ctime = util.TimeNow() var id int64 id, err = resource.Insert() if err != nil { logger.Errorln("Publish Resource error:", err) return } // 存扩展信息 resourceEx := model.NewResourceEx() resourceEx.Id = int(id) if _, err = resourceEx.Insert(); err != nil { logger.Errorln("PublishResource Ex error:", err) return } // 给 被@用户 发系统消息 /* ext := map[string]interface{}{ "objid": id, "objtype": model.TYPE_RESOURCE, "uid": user["uid"], "msgtype": model.MsgtypePublishAtMe, } go SendSysMsgAtUsernames(form.Get("usernames"), ext) */ // 发布主题,活跃度+10 go IncUserWeight("uid="+strconv.Itoa(uid), 10) } return }
// 获得某个分类的资源列表 // page 当前第几页 func FindResourcesByCatid(catid string, page int) (resources []map[string]interface{}, total int) { var offset = 0 if page > 1 { offset = (page - 1) * PAGE_NUM } resourceObj := model.NewResource() limit := strconv.Itoa(offset) + "," + strconv.Itoa(PAGE_NUM) resourceList, err := resourceObj.Where("catid=?", catid).Order("mtime DESC").Limit(limit).FindAll() if err != nil { logger.Errorln("resource service FindResourcesByCatid error:", err) return } // 获得该类别总资源数 total, err = resourceObj.Count() if err != nil { logger.Errorln("resource service resourceObj.Count Error:", err) return } count := len(resourceList) ids := make([]int, count) uids := make([]int, count) for i, resource := range resourceList { ids[i] = resource.Id uids[i] = resource.Uid } // 获取扩展信息(计数) resourceExList, err := model.NewResourceEx().Where("id in(" + util.Join(ids, ",") + ")").FindAll() if err != nil { logger.Errorln("resource service FindResourcesByCatid Error:", err) return } resourceExMap := make(map[int]*model.ResourceEx, len(resourceExList)) for _, resourceEx := range resourceExList { resourceExMap[resourceEx.Id] = resourceEx } userMap := GetUserInfos(uids) resources = make([]map[string]interface{}, count) for i, resource := range resourceList { tmpMap := make(map[string]interface{}) util.Struct2Map(tmpMap, resource) util.Struct2Map(tmpMap, resourceExMap[resource.Id]) tmpMap["user"] = userMap[resource.Uid] // 链接的host if resource.Form == model.LinkForm { urlObj, err := url.Parse(resource.Url) if err == nil { tmpMap["host"] = urlObj.Host } } else { tmpMap["url"] = "/resources/" + strconv.Itoa(resource.Id) } resources[i] = tmpMap } return }