412 lines
14 KiB
Go
412 lines
14 KiB
Go
package dao
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
artmdl "go-common/app/interface/openplatform/article/model"
|
|
"go-common/app/job/openplatform/article/model"
|
|
"go-common/library/database/sql"
|
|
"go-common/library/log"
|
|
"go-common/library/xstr"
|
|
)
|
|
|
|
const (
|
|
_sharding = 100
|
|
|
|
// stat
|
|
_statSQL = "SELECT article_id,favorite,reply,share,likes,dislike,view,coin FROM article_stats_%s WHERE article_id=%d and deleted_time =0"
|
|
_upStatSQL = `INSERT INTO article_stats_%s (article_id,favorite,reply,share,likes,dislike,view,coin) VALUES (?,?,?,?,?,?,?,?)
|
|
ON DUPLICATE KEY UPDATE favorite=?,reply=?,share=?,likes=?,dislike=?,view=?,coin=?`
|
|
_updateSearch = `INSERT INTO search_articles(ctime, article_id, category_id, title, summary, template_id, mid, image_urls, publish_time, content, tags, stats_view, stats_favorite, stats_likes, stats_dislike, stats_reply, stats_share, stats_coin, origin_image_urls, attributes, keywords)
|
|
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE ctime = ?, category_id =?, title=?, summary=?, template_id=?, mid=?, image_urls=?, publish_time=?, content=?, tags=?, stats_view=?, stats_favorite=?, stats_likes=?, stats_dislike=?, stats_reply=?, stats_share=?, stats_coin = ?, origin_image_urls = ?, attributes = ?, keywords = ?`
|
|
_delSearch = "DELETE FROM search_articles where article_id = ?"
|
|
_articleContentSQL = "SELECT content FROM filtered_article_contents_%s WHERE article_id = ?"
|
|
_updateSearchStats = "UPDATE search_articles SET stats_view=?, stats_favorite=?, stats_likes=?, stats_dislike=?, stats_reply=?, stats_share=?, stats_coin =? where article_id = ?"
|
|
_gameList = "SELECT mid FROM white_list_users WHERE group_id = 4 AND deleted = 0"
|
|
_allCheat = "SELECT article_id, lv FROM stats_filters WHERE deleted_time = 0"
|
|
_newestArtsMetaSQL = "SELECT article_id, publish_time, attributes FROM filtered_articles ORDER BY publish_time DESC LIMIT ?"
|
|
_newestArtCategorysMetaSQL = "SELECT article_id, publish_time, attributes FROM filtered_articles where category_id in (%s) ORDER BY publish_time DESC LIMIT %d"
|
|
_searchArticles = "select article_id, category_id, attributes, stats_view, stats_reply, stats_favorite, stats_likes, stats_coin from search_articles where publish_time >= ? and publish_time < ?"
|
|
_checkStateSQL = "SELECT publish_time,check_state FROM articles WHERE id = ? and deleted_time = 0"
|
|
_updateCheckState = "UPDATE articles SET check_state = 3 WHERE id = ?"
|
|
_settingsSQL = "SELECT name,value FROM article_settings WHERE deleted_time=0"
|
|
_midsByPublishTimeSQL = "SELECT mid FROM articles WHERE publish_time > ? and state = 0 and deleted_time = 0 group by mid"
|
|
_statByMidSQL = "select count(*), sum(words), category_id from articles where mid = ? and state = 0 and deleted_time = 0 group by category_id"
|
|
_keywordsSQL = "select tags from article_contents_%s where article_id = ?"
|
|
_actIDSQL = "select act_id from articles where id = ?"
|
|
_lastModsArtsSQL = "select id from articles where state in (0,5,6,7) and deleted_time = 0 order by mtime desc limit ?"
|
|
)
|
|
|
|
var _searchInterval = int64(3 * 24 * 3600)
|
|
|
|
func (d *Dao) hit(id int64) string {
|
|
return fmt.Sprintf("%02d", id%_sharding)
|
|
}
|
|
|
|
// Stat returns stat info.
|
|
func (d *Dao) Stat(c context.Context, aid int64) (stat *artmdl.StatMsg, err error) {
|
|
stat = &artmdl.StatMsg{}
|
|
err = d.db.QueryRow(c, fmt.Sprintf(_statSQL, d.hit(aid), aid)).Scan(&stat.Aid, &stat.Favorite, &stat.Reply, &stat.Share, &stat.Like, &stat.Dislike, &stat.View, &stat.Coin)
|
|
if err == sql.ErrNoRows {
|
|
err = nil
|
|
stat = nil
|
|
} else if err != nil {
|
|
log.Error("Stat(%v) error(%+v)", aid, err)
|
|
PromError("db:读取计数")
|
|
}
|
|
return
|
|
}
|
|
|
|
// Update updates stat in db.
|
|
func (d *Dao) Update(c context.Context, stat *artmdl.StatMsg) (rows int64, err error) {
|
|
res, err := d.db.Exec(c, fmt.Sprintf(_upStatSQL, d.hit(stat.Aid)), stat.Aid, *stat.Favorite, *stat.Reply, *stat.Share, *stat.Like, *stat.Dislike, *stat.View, *stat.Coin,
|
|
*stat.Favorite, *stat.Reply, *stat.Share, *stat.Like, *stat.Dislike, *stat.View, *stat.Coin)
|
|
if err != nil {
|
|
log.Error("Update(%d,%+v) error(%+v)", stat.Aid, stat, err)
|
|
PromError("db:更新计数")
|
|
return
|
|
}
|
|
rows, err = res.RowsAffected()
|
|
return
|
|
}
|
|
|
|
// UpdateSearch update search article table
|
|
func (d *Dao) UpdateSearch(c context.Context, a *model.SearchArticle) (err error) {
|
|
_, err = d.updateSearchStmt.Exec(c, a.CTime, a.ID, a.CategoryID, a.Title, a.Summary, a.TemplateID, a.Mid, a.ImageURLs, a.PublishTime, a.Content, a.Tags, a.StatsView, a.StatsFavorite, a.StatsLikes, a.StatsDisLike, a.StatsReply, a.StatsShare, a.StatsCoin, a.OriginImageURLs, a.Attributes, a.Keywords,
|
|
a.CTime, a.CategoryID, a.Title, a.Summary, a.TemplateID, a.Mid, a.ImageURLs, a.PublishTime, a.Content, a.Tags, a.StatsView, a.StatsFavorite, a.StatsLikes, a.StatsDisLike, a.StatsReply, a.StatsShare, a.StatsCoin, a.OriginImageURLs, a.Attributes, a.Keywords)
|
|
if err != nil {
|
|
PromError("db:更新搜索表")
|
|
log.Error("UpdateSearch(%+v) error(%+v)", a, err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// DelSearch del search article table
|
|
func (d *Dao) DelSearch(c context.Context, aid int64) (err error) {
|
|
_, err = d.delSearchStmt.Exec(c, aid)
|
|
if err != nil {
|
|
PromError("db:删除搜索表")
|
|
log.Error("DelSearch(%v) error(%+v)", aid, err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// UpdateRecheck update recheck table
|
|
func (d *Dao) UpdateRecheck(c context.Context, aid int64) (err error) {
|
|
_, err = d.updateRecheckStmt.Exec(c, aid)
|
|
if err != nil {
|
|
PromError("db:修改回查状态")
|
|
log.Error("UpdateRecheck(%v) error(%+v)", aid, err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// ArticleContent get article content
|
|
func (d *Dao) ArticleContent(c context.Context, id int64) (res string, err error) {
|
|
contentSQL := fmt.Sprintf(_articleContentSQL, d.hit(id))
|
|
if err = d.db.QueryRow(c, contentSQL, id).Scan(&res); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
err = nil
|
|
return
|
|
}
|
|
PromError("db:ArticleContent")
|
|
log.Error("dao.ArticleContent(%s) error(%+v)", contentSQL, err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// GetRecheckInfo get article recheck
|
|
func (d *Dao) GetRecheckInfo(c context.Context, id int64) (publishTime int64, checkState int, err error) {
|
|
if err = d.getRecheckStmt.QueryRow(c, id).Scan(&publishTime, &checkState); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
err = nil
|
|
return
|
|
}
|
|
PromError("db:ReCheckQuery")
|
|
log.Error("dao.GetRecheckInfo(%d) error(%+v)", id, err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// UpdateSearchStats update search stats
|
|
func (d *Dao) UpdateSearchStats(c context.Context, stat *artmdl.StatMsg) (err error) {
|
|
_, err = d.updateSearchStatsStmt.Exec(c, *stat.View, *stat.Favorite, *stat.Like, *stat.Dislike, *stat.Reply, *stat.Share, *stat.Coin, stat.Aid)
|
|
if err != nil {
|
|
log.Error("updateSearchStatsStmt(%d,%+v) error(%+v)", stat.Aid, stat, err)
|
|
PromError("db:更新搜索计数")
|
|
}
|
|
return
|
|
}
|
|
|
|
// RawGameList game list
|
|
func (d *Dao) RawGameList(c context.Context) (mids []int64, err error) {
|
|
rows, err := d.gameStmt.Query(c)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var id int64
|
|
if rows.Scan(&id); err != nil {
|
|
PromError("db:GameList")
|
|
log.Error("dao.GameList() error(%+v)", err)
|
|
return
|
|
}
|
|
mids = append(mids, id)
|
|
}
|
|
return
|
|
}
|
|
|
|
// CheatArts cheat list
|
|
func (d *Dao) CheatArts(c context.Context) (res map[int64]int, err error) {
|
|
rows, err := d.cheatStmt.Query(c)
|
|
if err != nil {
|
|
return
|
|
}
|
|
res = make(map[int64]int)
|
|
defer rows.Close()
|
|
defer func() {
|
|
if err != nil {
|
|
PromError("db:CheatArts")
|
|
log.Error("dao.CheatArts() error(%+v)", err)
|
|
}
|
|
}()
|
|
for rows.Next() {
|
|
var id int64
|
|
var lv int
|
|
if rows.Scan(&id, &lv); err != nil {
|
|
return
|
|
}
|
|
res[id] = lv
|
|
}
|
|
err = rows.Err()
|
|
return
|
|
}
|
|
|
|
// NewestArtIDs find newest article's id
|
|
func (d *Dao) NewestArtIDs(c context.Context, limit int64) (res [][2]int64, err error) {
|
|
rows, err := d.newestArtsMetaStmt.Query(c, limit)
|
|
if err != nil {
|
|
PromError("db:最新文章")
|
|
log.Error("dao.newestArtsMetaStmt.Query error(%+v)", err)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var (
|
|
id int64
|
|
ptime int64
|
|
attribute int32
|
|
)
|
|
if err = rows.Scan(&id, &ptime, &attribute); err != nil {
|
|
PromError("db:最新文章scan")
|
|
log.Error("dao.NewestArtIDs.rows.Scan error(%+v)", err)
|
|
return
|
|
}
|
|
if artmdl.NoDistributeAttr(attribute) || artmdl.NoRegionAttr(attribute) {
|
|
continue
|
|
}
|
|
res = append(res, [2]int64{id, ptime})
|
|
}
|
|
if err = rows.Err(); err != nil {
|
|
PromError("db:最新文章")
|
|
log.Error("dao.NewestArtIDs.rows error(%+v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// NewestArtIDByCategory find newest article's id
|
|
func (d *Dao) NewestArtIDByCategory(c context.Context, cids []int64, limit int64) (res [][2]int64, err error) {
|
|
sql := fmt.Sprintf(_newestArtCategorysMetaSQL, xstr.JoinInts(cids), limit)
|
|
rows, err := d.db.Query(c, sql)
|
|
if err != nil {
|
|
PromError("db:最新文章")
|
|
log.Error("dao.NewestArtIDByCategorys.Query error(%+v)", err)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var (
|
|
id int64
|
|
ptime int64
|
|
attribute int32
|
|
)
|
|
if err = rows.Scan(&id, &ptime, &attribute); err != nil {
|
|
PromError("db:最新文章scan")
|
|
log.Error("dao.NewestArtIDByCategory.rows.Scan error(%+v)", err)
|
|
return
|
|
}
|
|
if artmdl.NoDistributeAttr(attribute) || artmdl.NoRegionAttr(attribute) {
|
|
continue
|
|
}
|
|
res = append(res, [2]int64{id, ptime})
|
|
}
|
|
if err = rows.Err(); err != nil {
|
|
PromError("db:最新文章")
|
|
log.Error("dao.NewestArtIDByCategory.Scan error(%+v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// SearchArts get articles publish time after ptime
|
|
func (d *Dao) SearchArts(c context.Context, ptime int64) (res []*model.SearchArticle, err error) {
|
|
var rows *sql.Rows
|
|
now := time.Now().Unix()
|
|
for ; ptime < now; ptime += _searchInterval {
|
|
if rows, err = d.searchArtsStmt.Query(c, ptime, ptime+_searchInterval); err != nil {
|
|
PromError("db:searchArts")
|
|
log.Error("mysql: search arts Query() error(%+v)", err)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
ba := &model.SearchArticle{}
|
|
if err = rows.Scan(&ba.ID, &ba.CategoryID, &ba.Attributes, &ba.StatsView, &ba.StatsReply, &ba.StatsFavorite, &ba.StatsLikes, &ba.StatsCoin); err != nil {
|
|
PromError("db:searchArts")
|
|
log.Error("mysql: search arts Scan() error(%+v)", err)
|
|
return
|
|
}
|
|
res = append(res, ba)
|
|
}
|
|
if err = rows.Err(); err != nil {
|
|
PromError("db:searchArts")
|
|
log.Error("mysql: search arts Query() error(%+v)", err)
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// Settings gets article settings.
|
|
func (d *Dao) Settings(c context.Context) (res map[string]string, err error) {
|
|
var rows *sql.Rows
|
|
if rows, err = d.settingsStmt.Query(c); err != nil {
|
|
PromError("db:文章配置查询")
|
|
log.Error("mysql: db.settingsStmt.Query error(%+v)", err)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
res = make(map[string]string)
|
|
for rows.Next() {
|
|
var name, value string
|
|
if err = rows.Scan(&name, &value); err != nil {
|
|
PromError("文章配置scan")
|
|
log.Error("mysql: rows.Scan error(%+v)", err)
|
|
return
|
|
}
|
|
res[name] = value
|
|
}
|
|
err = rows.Err()
|
|
if err = rows.Err(); err != nil {
|
|
PromError("db:loadSettings")
|
|
log.Error("mysql: load settings Query() error(%+v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
//MidsByPublishTime get mids by publish time
|
|
func (d *Dao) MidsByPublishTime(c context.Context, pubTime int64) (mids []int64, err error) {
|
|
var rows *sql.Rows
|
|
if rows, err = d.midByPubtimeStmt.Query(c, pubTime); err != nil {
|
|
PromError("db:查询近7天mid")
|
|
log.Error("mysql: db.MidsByPublishTime.Query error(%+v)", err)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var mid int64
|
|
if err = rows.Scan(&mid); err != nil {
|
|
PromError("查询近7天mid scan")
|
|
log.Error("mysql: rows.Scan error(%+v)", err)
|
|
return
|
|
}
|
|
mids = append(mids, mid)
|
|
}
|
|
err = rows.Err()
|
|
if err = rows.Err(); err != nil {
|
|
PromError("db:MidsByPublishTime")
|
|
log.Error("mysql: get mids by publish time Query() error(%+v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
//StatByMid get author info by mid
|
|
func (d *Dao) StatByMid(c context.Context, mid int64) (res map[int64][2]int64, err error) {
|
|
res = make(map[int64][2]int64)
|
|
var rows *sql.Rows
|
|
if rows, err = d.statByMidStmt.Query(c, mid); err != nil {
|
|
PromError("db:作者分区数据")
|
|
log.Error("mysql: db.statByMidStmt.Query error(%+v)", err)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var (
|
|
data [2]int64
|
|
cate int64
|
|
)
|
|
if err = rows.Scan(&data[0], &data[1], &cate); err != nil {
|
|
PromError("作者分区数据 scan")
|
|
log.Error("mysql: rows.Scan error(%+v)", err)
|
|
return
|
|
}
|
|
res[cate] = data
|
|
}
|
|
err = rows.Err()
|
|
if err = rows.Err(); err != nil {
|
|
PromError("db:StatByMid")
|
|
log.Error("mysql: get stat infos by mid Query() error(%+v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Keywords .
|
|
func (d *Dao) Keywords(c context.Context, id int64) (keywords string, err error) {
|
|
var sqlStr = fmt.Sprintf(_keywordsSQL, d.hit(id))
|
|
row := d.db.QueryRow(c, sqlStr, id)
|
|
if err = row.Scan(&keywords); err != nil {
|
|
PromError("db:Keywords")
|
|
log.Error("d.keywords scan error(%+v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// IsAct .
|
|
func (d *Dao) IsAct(c context.Context, id int64) (res bool) {
|
|
var actID int64
|
|
if err := d.db.QueryRow(c, _actIDSQL, id).Scan(&actID); err != nil {
|
|
PromError("db:IsAct")
|
|
log.Error("d.IsAct scan error(%+v)", err)
|
|
return
|
|
}
|
|
if actID > 0 {
|
|
res = true
|
|
}
|
|
return
|
|
}
|
|
|
|
// LastModIDs .
|
|
func (d *Dao) LastModIDs(c context.Context, size int) (aids []int64, err error) {
|
|
var (
|
|
id int64
|
|
rows *sql.Rows
|
|
)
|
|
if rows, err = d.db.Query(c, _lastModsArtsSQL, size); err != nil {
|
|
PromError("db:LastModIDs")
|
|
log.Error("d.LastModIDs query error(%+v) size(%d)", err, size)
|
|
return
|
|
}
|
|
for rows.Next() {
|
|
if err = rows.Scan(&id); err != nil {
|
|
PromError("db:LastModIDs")
|
|
log.Error("d.LastModIDs scan error(%+v) size(%d)", err, size)
|
|
return
|
|
}
|
|
aids = append(aids, id)
|
|
}
|
|
return
|
|
}
|