You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
509 lines
20 KiB
509 lines
20 KiB
package dao |
|
|
|
import ( |
|
"bytes" |
|
"context" |
|
"crypto/hmac" |
|
"crypto/sha1" |
|
"encoding/base64" |
|
"encoding/json" |
|
"errors" |
|
"fmt" |
|
"hash" |
|
"net/http" |
|
"strconv" |
|
"strings" |
|
"time" |
|
|
|
"database/sql" |
|
artmdl "go-common/app/interface/openplatform/article/model" |
|
xsql "go-common/library/database/sql" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
xtime "go-common/library/time" |
|
"go-common/library/xstr" |
|
) |
|
|
|
const ( |
|
// article |
|
_addArticleMetaSQL = "INSERT INTO articles (category_id,title,summary,banner_url,template_id,state,mid,reprint,image_urls,attributes,words,dynamic_intro,origin_image_urls,act_id,media_id,spoiler,apply_time) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" |
|
_addArticleContentSQL = "INSERT INTO article_contents_%s (article_id,content,tags) values (?,?,?)" |
|
_addArticleVersionSQL = "INSERT INTO article_versions (article_id,category_id,title,state,content,summary,banner_url,template_id,mid,reprint,image_urls,attributes,words,dynamic_intro,origin_image_urls,act_id,media_id,spoiler,apply_time,ext_msg)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" |
|
_updateArticleVersionSQL = "UPDATE article_versions SET category_id=?,title=?,state=?,content=?,summary=?,banner_url=?,template_id=?,mid=?,reprint=?,image_urls=?,attributes=?,words=?,dynamic_intro=?,origin_image_urls=?,spoiler=?,apply_time=?,ext_msg=? where article_id=? and deleted_time=0" |
|
_updateArticleMetaSQL = "UPDATE articles SET category_id=?,title=?,summary=?,banner_url=?,template_id=?,state=?,mid=?,reprint=?,image_urls=?,attributes=?,words=?,dynamic_intro=?,origin_image_urls =?,spoiler=?,apply_time=? WHERE id=?" |
|
_updateArticleContentSQL = "UPDATE article_contents_%s SET content=?, tags=? WHERE article_id=?" |
|
_deleteArticleMetaSQL = "UPDATE articles SET deleted_time=? WHERE id=?" |
|
_deleteArticleContentSQL = "UPDATE article_contents_%s SET deleted_time=? WHERE article_id=?" |
|
_deleteArticleVerionSQL = "UPDATE article_versions SET deleted_time=? WHERE article_id=?" |
|
_updateArticleStateSQL = "UPDATE articles SET state=? WHERE id=?" |
|
_updateArticleStateApplyTimeSQL = "UPDATE articles SET state=?,apply_time=? WHERE id=?" |
|
_upperArticlesMetaCreationSQL = `SELECT id,category_id,title,summary,banner_url,template_id,state,mid,reprint,image_urls,publish_time,ctime,reason, attributes, dynamic_intro, origin_image_urls FROM articles WHERE mid=? and deleted_time=0 |
|
and state in (%s)` |
|
_upperArticleCountCreationSQL = "SELECT state FROM articles WHERE mid=? and deleted_time=0" |
|
_articleMetaCreationSQL = "SELECT id,category_id,title,summary,banner_url, template_id, state, mid, reprint, image_urls, publish_time,ctime, attributes, dynamic_intro, origin_image_urls, media_id, spoiler FROM articles WHERE id = ? and deleted_time = 0" |
|
_articleContentCreationSQL = "SELECT content FROM article_contents_%s WHERE article_id=? AND deleted_time=0" |
|
_countEditTimesSQL = "SELECT count(*) FROM article_histories_%s WHERE article_id=? AND deleted_time=0 AND state in (5,6,7)" |
|
_articleVersionSQL = "SELECT article_id,category_id,title,state,content,summary,banner_url,template_id,reprint,image_urls,attributes,words,dynamic_intro,origin_image_urls,media_id,spoiler,apply_time,ext_msg FROM article_versions WHERE article_id=? AND deleted_time=0" |
|
_reasonOfVersion = "SELECT reason FROM article_versions WHERE article_id=? AND state=? AND deleted_time=0 ORDER BY id DESC LIMIT 1" |
|
) |
|
|
|
// TxAddArticleMeta adds article's meta via transaction. |
|
func (d *Dao) TxAddArticleMeta(c context.Context, tx *xsql.Tx, a *artmdl.Meta, actID int64) (id int64, err error) { |
|
a.ImageURLs = artmdl.CleanURLs(a.ImageURLs) |
|
a.OriginImageURLs = artmdl.CleanURLs(a.OriginImageURLs) |
|
a.BannerURL = artmdl.CleanURL(a.BannerURL) |
|
var ( |
|
res sql.Result |
|
imageUrls = strings.Join(a.ImageURLs, ",") |
|
originImageUrls = strings.Join(a.OriginImageURLs, ",") |
|
applyTime = time.Now().Format("2006-01-02 15:04:05") |
|
) |
|
if res, err = tx.Exec(_addArticleMetaSQL, a.Category.ID, a.Title, a.Summary, a.BannerURL, a.TemplateID, a.State, a.Author.Mid, a.Reprint, imageUrls, a.Attributes, a.Words, a.Dynamic, originImageUrls, actID, a.Media.MediaID, a.Media.Spoiler, applyTime); err != nil { |
|
PromError("db:新增文章meta") |
|
log.Error("tx.Exec() error(%+v)", err) |
|
return |
|
} |
|
if id, err = res.LastInsertId(); err != nil { |
|
log.Error("res.LastInsertId() error(%+v)", err) |
|
} |
|
return |
|
} |
|
|
|
// TxAddArticleContent adds article's body via transaction. |
|
func (d *Dao) TxAddArticleContent(c context.Context, tx *xsql.Tx, aid int64, content string, tags []string) (err error) { |
|
|
|
var sqlStr = fmt.Sprintf(_addArticleContentSQL, d.hit(aid)) |
|
if _, err = tx.Exec(sqlStr, aid, content, strings.Join(tags, "\001")); err != nil { |
|
PromError("db:新增文章content") |
|
log.Error("tx.Exec(%s,%d) error(%+v)", sqlStr, aid, err) |
|
} |
|
return |
|
} |
|
|
|
// TxAddArticleVersion adds article version. |
|
func (d *Dao) TxAddArticleVersion(c context.Context, tx *xsql.Tx, id int64, a *artmdl.Article, actID int64) (err error) { |
|
a.ImageURLs = artmdl.CleanURLs(a.ImageURLs) |
|
a.OriginImageURLs = artmdl.CleanURLs(a.OriginImageURLs) |
|
a.BannerURL = artmdl.CleanURL(a.BannerURL) |
|
var ( |
|
applyTime = time.Now().Format("2006-01-02 15:04:05") |
|
imageUrls = strings.Join(a.ImageURLs, ",") |
|
originImageUrls = strings.Join(a.OriginImageURLs, ",") |
|
extMsg = &artmdl.ExtMsg{ |
|
Tags: a.Tags, |
|
} |
|
extStr []byte |
|
) |
|
if extStr, err = json.Marshal(extMsg); err != nil { |
|
log.Error("json.Marshal error(%+v)", err) |
|
return |
|
} |
|
if _, err = tx.Exec(_addArticleVersionSQL, id, a.Category.ID, a.Title, a.State, a.Content, a.Summary, a.BannerURL, a.TemplateID, a.Author.Mid, a.Reprint, imageUrls, a.Attributes, a.Words, a.Dynamic, originImageUrls, actID, a.Media.MediaID, a.Media.Spoiler, applyTime, string(extStr)); err != nil { |
|
PromError("db:新增版本") |
|
log.Error("tx.Exec() error(%+v)", err) |
|
} |
|
return |
|
} |
|
|
|
// TxUpdateArticleVersion updates article version. |
|
func (d *Dao) TxUpdateArticleVersion(c context.Context, tx *xsql.Tx, id int64, a *artmdl.Article, actID int64) (err error) { |
|
a.ImageURLs = artmdl.CleanURLs(a.ImageURLs) |
|
a.OriginImageURLs = artmdl.CleanURLs(a.OriginImageURLs) |
|
a.BannerURL = artmdl.CleanURL(a.BannerURL) |
|
var ( |
|
applyTime = time.Now().Format("2006-01-02 15:04:05") |
|
imageUrls = strings.Join(a.ImageURLs, ",") |
|
originImageUrls = strings.Join(a.OriginImageURLs, ",") |
|
extMsg = &artmdl.ExtMsg{ |
|
Tags: a.Tags, |
|
} |
|
extStr []byte |
|
) |
|
if extStr, err = json.Marshal(extMsg); err != nil { |
|
log.Error("json.Marshal error(%+v)", err) |
|
return |
|
} |
|
if _, err = tx.Exec(_updateArticleVersionSQL, a.Category.ID, a.Title, a.State, a.Content, a.Summary, a.BannerURL, a.TemplateID, a.Author.Mid, a.Reprint, imageUrls, a.Attributes, a.Words, a.Dynamic, originImageUrls, a.Media.Spoiler, applyTime, string(extStr), id); err != nil { |
|
PromError("db:更新版本") |
|
log.Error("tx.Exec() error(%+v)", err) |
|
} |
|
return |
|
} |
|
|
|
// TxUpdateArticleMeta updates article's meta via transaction. |
|
func (d *Dao) TxUpdateArticleMeta(c context.Context, tx *xsql.Tx, a *artmdl.Meta) (err error) { |
|
a.ImageURLs = artmdl.CleanURLs(a.ImageURLs) |
|
a.OriginImageURLs = artmdl.CleanURLs(a.OriginImageURLs) |
|
a.BannerURL = artmdl.CleanURL(a.BannerURL) |
|
var ( |
|
imageURLs = strings.Join(a.ImageURLs, ",") |
|
originImageURLs = strings.Join(a.OriginImageURLs, ",") |
|
applyTime = time.Now().Format("2006-01-02 15:04:05") |
|
) |
|
if _, err = tx.Exec(_updateArticleMetaSQL, a.Category.ID, a.Title, a.Summary, a.BannerURL, a.TemplateID, a.State, a.Author.Mid, a.Reprint, imageURLs, a.Attributes, a.Words, a.Dynamic, originImageURLs, a.Media.Spoiler, applyTime, a.ID); err != nil { |
|
PromError("db:更新文章meta") |
|
log.Error("tx.Exec() error(%+v)", err) |
|
} |
|
return |
|
} |
|
|
|
// TxUpdateArticleContent updates article's body via transaction. |
|
func (d *Dao) TxUpdateArticleContent(c context.Context, tx *xsql.Tx, aid int64, content string, tags []string) (err error) { |
|
var sqlStr = fmt.Sprintf(_updateArticleContentSQL, d.hit(aid)) |
|
if _, err = tx.Exec(sqlStr, content, strings.Join(tags, "\001"), aid); err != nil { |
|
PromError("db:更新文章content") |
|
log.Error("tx.Exec(%s,%d) error(%+v)", sqlStr, aid, err) |
|
} |
|
return |
|
} |
|
|
|
// TxDeleteArticleMeta deletes article's meta via transaction. |
|
func (d *Dao) TxDeleteArticleMeta(c context.Context, tx *xsql.Tx, aid int64) (err error) { |
|
var now = time.Now().Unix() |
|
if _, err = tx.Exec(_deleteArticleMetaSQL, now, aid); err != nil { |
|
PromError("db:删除文章meta") |
|
log.Error("tx.Exec() error(%+v)", err) |
|
} |
|
return |
|
} |
|
|
|
// TxDeleteArticleContent deletes article's meta via transaction. |
|
func (d *Dao) TxDeleteArticleContent(c context.Context, tx *xsql.Tx, aid int64) (err error) { |
|
var ( |
|
now = time.Now().Unix() |
|
sqlStr = fmt.Sprintf(_deleteArticleContentSQL, d.hit(aid)) |
|
) |
|
if _, err = tx.Exec(sqlStr, now, aid); err != nil { |
|
PromError("db:删除文章content") |
|
log.Error("tx.Exec(%s,%d,%d) error(%+v)", sqlStr, now, aid, err) |
|
} |
|
return |
|
} |
|
|
|
// TxDelArticleVersion deletes article version. |
|
func (d *Dao) TxDelArticleVersion(c context.Context, tx *xsql.Tx, aid int64) (err error) { |
|
var now = time.Now().Unix() |
|
if _, err = tx.Exec(_deleteArticleVerionSQL, now, aid); err != nil { |
|
PromError("db:删除文章版本content") |
|
log.Error("tx.Exec(%s,%d,%d) error(%+v)", _deleteArticleVerionSQL, now, aid, err) |
|
} |
|
return |
|
} |
|
|
|
// TxDelFilteredArtMeta delete filetered article meta |
|
func (d *Dao) TxDelFilteredArtMeta(c context.Context, tx *xsql.Tx, aid int64) (err error) { |
|
if _, err = tx.Exec(_delFilteredArtMetaSQL, aid); err != nil { |
|
PromError("db:删除过滤文章") |
|
log.Error("dao.DelFilteredArtMeta exec(%v) error(%+v)", aid, err) |
|
} |
|
return |
|
} |
|
|
|
//TxDelFilteredArtContent delete filtered article content |
|
func (d *Dao) TxDelFilteredArtContent(c context.Context, tx *xsql.Tx, aid int64) (err error) { |
|
contentSQL := fmt.Sprintf(_delFilteredArtContentSQL, d.hit(aid)) |
|
if _, err = tx.Exec(contentSQL, aid); err != nil { |
|
PromError("db:删除过滤文章正文") |
|
log.Error("dao.DelFilteredArtContent exec(%v) error(%+v)", aid, err) |
|
} |
|
return |
|
} |
|
|
|
// UpdateArticleState updates article's state. |
|
func (d *Dao) UpdateArticleState(c context.Context, aid int64, state int) (err error) { |
|
var res sql.Result |
|
if res, err = d.updateArticleStateStmt.Exec(c, state, aid); err != nil { |
|
PromError("db:更新文章状态") |
|
log.Error("s.dao.UpdateArticleState.Exec(aid: %v, state: %v) error(%+v)", aid, state, err) |
|
return |
|
} |
|
if count, _ := res.RowsAffected(); count == 0 { |
|
err = ecode.NothingFound |
|
} |
|
return |
|
} |
|
|
|
// TxUpdateArticleState updates article's state. |
|
func (d *Dao) TxUpdateArticleState(c context.Context, tx *xsql.Tx, aid int64, state int32) (err error) { |
|
var res sql.Result |
|
if res, err = tx.Exec(_updateArticleStateSQL, state, aid); err != nil { |
|
PromError("db:更新文章状态") |
|
log.Error("s.dao.TxUpdateArticleState.Exec(aid: %v, state: %v) error(%+v)", aid, state, err) |
|
return |
|
} |
|
if count, _ := res.RowsAffected(); count == 0 { |
|
err = ecode.NothingFound |
|
} |
|
return |
|
} |
|
|
|
// TxUpdateArticleStateApplyTime updates article's state and apply time. |
|
func (d *Dao) TxUpdateArticleStateApplyTime(c context.Context, tx *xsql.Tx, aid int64, state int32) (err error) { |
|
var ( |
|
res sql.Result |
|
applyTime = time.Now().Format("2006-01-02 15:03:04") |
|
) |
|
if res, err = tx.Exec(_updateArticleStateApplyTimeSQL, state, applyTime, aid); err != nil { |
|
PromError("db:更新文章状态和申请时间") |
|
log.Error("s.dao.TxUpdateArticleStateApplyTime.Exec(aid: %v, state: %v) error(%+v)", aid, state, err) |
|
return |
|
} |
|
if count, _ := res.RowsAffected(); count == 0 { |
|
err = ecode.NothingFound |
|
} |
|
return |
|
} |
|
|
|
// UpperArticlesMeta gets article list by mid. |
|
func (d *Dao) UpperArticlesMeta(c context.Context, mid int64, group, category int) (as []*artmdl.Meta, err error) { |
|
var ( |
|
rows *xsql.Rows |
|
sqlStr string |
|
) |
|
sqlStr = fmt.Sprintf(_upperArticlesMetaCreationSQL, xstr.JoinInts(artmdl.Group2State(group))) |
|
if category > 0 { |
|
sqlStr += " and category_id=" + strconv.Itoa(category) |
|
} |
|
if rows, err = d.articleDB.Query(c, sqlStr, mid); err != nil { |
|
PromError("db:获取文章meta") |
|
log.Error("d.articleDB.Query(%s,%s) error(%+v)", sqlStr, err) |
|
return |
|
} |
|
defer rows.Close() |
|
for rows.Next() { |
|
a := &artmdl.Meta{Category: &artmdl.Category{}, Author: &artmdl.Author{}} |
|
var ( |
|
ptime int64 |
|
ctime time.Time |
|
imageURLs, originImageURLs string |
|
) |
|
if err = rows.Scan(&a.ID, &a.Category.ID, &a.Title, &a.Summary, &a.BannerURL, &a.TemplateID, &a.State, &a.Author.Mid, &a.Reprint, &imageURLs, &ptime, &ctime, &a.Reason, &a.Attributes, &a.Dynamic, &originImageURLs); err != nil { |
|
promErrorCheck(err) |
|
log.Error("rows.Scan error(%+v)", err) |
|
return |
|
} |
|
if imageURLs == "" { |
|
a.ImageURLs = []string{} |
|
} else { |
|
a.ImageURLs = strings.Split(imageURLs, ",") |
|
} |
|
if originImageURLs == "" { |
|
a.OriginImageURLs = []string{} |
|
} else { |
|
a.OriginImageURLs = strings.Split(originImageURLs, ",") |
|
} |
|
a.PublishTime = xtime.Time(ptime) |
|
a.Ctime = xtime.Time(ctime.Unix()) |
|
a.BannerURL = artmdl.CompleteURL(a.BannerURL) |
|
a.ImageURLs = artmdl.CompleteURLs(a.ImageURLs) |
|
a.OriginImageURLs = artmdl.CompleteURLs(a.OriginImageURLs) |
|
as = append(as, a) |
|
} |
|
err = rows.Err() |
|
promErrorCheck(err) |
|
return |
|
} |
|
|
|
// UpperArticlesTypeCount gets article count by type. |
|
func (d *Dao) UpperArticlesTypeCount(c context.Context, mid int64) (res *artmdl.CreationArtsType, err error) { |
|
var rows *xsql.Rows |
|
res = &artmdl.CreationArtsType{} |
|
if rows, err = d.upperArtCntCreationStmt.Query(c, mid); err != nil { |
|
PromError("db:获取各种文章状态总数") |
|
log.Error("d.articleDB.Query(%d) error(%+v)", mid, err) |
|
return |
|
} |
|
defer rows.Close() |
|
for rows.Next() { |
|
var state int |
|
if err = rows.Scan(&state); err != nil { |
|
promErrorCheck(err) |
|
return |
|
} |
|
switch state { |
|
case artmdl.StateAutoLock, artmdl.StateLock, artmdl.StateReject, artmdl.StateOpenReject: |
|
res.NotPassed++ |
|
case artmdl.StateAutoPass, artmdl.StateOpen, artmdl.StateRePass, artmdl.StateReReject: |
|
res.Passed++ |
|
case artmdl.StatePending, artmdl.StateOpenPending, artmdl.StateRePending: |
|
res.Audit++ |
|
} |
|
} |
|
err = rows.Err() |
|
promErrorCheck(err) |
|
res.All = res.NotPassed + res.Passed + res.Audit |
|
return |
|
} |
|
|
|
// CreationArticleMeta querys article's meta info for creation center by aid. |
|
func (d *Dao) CreationArticleMeta(c context.Context, id int64) (am *artmdl.Meta, err error) { |
|
var ( |
|
imageURLs, originImageURLs string |
|
category = &artmdl.Category{} |
|
author = &artmdl.Author{} |
|
ptime int64 |
|
ct time.Time |
|
) |
|
am = &artmdl.Meta{Media: &artmdl.Media{}} |
|
if err = d.articleMetaCreationStmt.QueryRow(c, id).Scan(&am.ID, &category.ID, &am.Title, &am.Summary, |
|
&am.BannerURL, &am.TemplateID, &am.State, &author.Mid, &am.Reprint, &imageURLs, &ptime, &ct, &am.Attributes, &am.Dynamic, &originImageURLs, &am.Media.MediaID, &am.Media.Spoiler); err != nil { |
|
if err == sql.ErrNoRows { |
|
err = nil |
|
am = nil |
|
return |
|
} |
|
PromError("db:文章内容表") |
|
log.Error("row.ArticleContent.QueryRow error(%+v)", err) |
|
return |
|
} |
|
am.Category = category |
|
am.Author = author |
|
am.Ctime = xtime.Time(ct.Unix()) |
|
if imageURLs == "" { |
|
am.ImageURLs = []string{} |
|
} else { |
|
am.ImageURLs = strings.Split(imageURLs, ",") |
|
} |
|
if originImageURLs == "" { |
|
am.OriginImageURLs = []string{} |
|
} else { |
|
am.OriginImageURLs = strings.Split(originImageURLs, ",") |
|
} |
|
am.PublishTime = xtime.Time(ptime) |
|
am.BannerURL = artmdl.CompleteURL(am.BannerURL) |
|
am.ImageURLs = artmdl.CompleteURLs(am.ImageURLs) |
|
am.OriginImageURLs = artmdl.CompleteURLs(am.OriginImageURLs) |
|
return |
|
} |
|
|
|
// CreationArticleContent gets article's content. |
|
func (d *Dao) CreationArticleContent(c context.Context, aid int64) (res string, err error) { |
|
contentSQL := fmt.Sprintf(_articleContentCreationSQL, d.hit(aid)) |
|
if err = d.articleDB.QueryRow(c, contentSQL, aid).Scan(&res); err != nil { |
|
if err == sql.ErrNoRows { |
|
err = nil |
|
return |
|
} |
|
PromError("db:CreationArticleContent") |
|
log.Error("dao.CreationArticleContent(%s) error(%+v)", contentSQL, err) |
|
} |
|
return |
|
} |
|
|
|
// UploadImage upload bfs. |
|
func (d *Dao) UploadImage(c context.Context, fileType string, bs []byte) (location string, err error) { |
|
req, err := http.NewRequest(d.c.BFS.Method, d.c.BFS.URL, bytes.NewBuffer(bs)) |
|
if err != nil { |
|
PromError("creation:UploadImage") |
|
log.Error("creation: http.NewRequest error (%v) | fileType(%s)", err, fileType) |
|
return |
|
} |
|
expire := time.Now().Unix() |
|
authorization := authorize(d.c.BFS.Key, d.c.BFS.Secret, d.c.BFS.Method, d.c.BFS.Bucket, expire) |
|
req.Header.Set("Host", d.c.BFS.URL) |
|
req.Header.Add("Date", fmt.Sprint(expire)) |
|
req.Header.Add("Authorization", authorization) |
|
req.Header.Add("Content-Type", fileType) |
|
// timeout |
|
ctx, cancel := context.WithTimeout(c, time.Duration(d.c.BFS.Timeout)) |
|
req = req.WithContext(ctx) |
|
defer cancel() |
|
resp, err := d.bfsClient.Do(req) |
|
if err != nil { |
|
PromError("creation:UploadImage") |
|
log.Error("creation: d.Client.Do error(%v) | url(%s)", err, d.c.BFS.URL) |
|
err = ecode.BfsUploadServiceUnavailable |
|
return |
|
} |
|
if resp.StatusCode != http.StatusOK { |
|
log.Error("creation: Upload http.StatusCode nq http.StatusOK (%d) | url(%s)", resp.StatusCode, d.c.BFS.URL) |
|
PromError("creation:UploadImage") |
|
err = errors.New("Upload failed") |
|
return |
|
} |
|
header := resp.Header |
|
code := header.Get("Code") |
|
if code != strconv.Itoa(http.StatusOK) { |
|
log.Error("creation: strconv.Itoa err, code(%s) | url(%s)", code, d.c.BFS.URL) |
|
PromError("creation:UploadImage") |
|
err = errors.New("Upload failed") |
|
return |
|
} |
|
location = header.Get("Location") |
|
return |
|
} |
|
|
|
// authorize returns authorization for upload file to bfs |
|
func authorize(key, secret, method, bucket string, expire int64) (authorization string) { |
|
var ( |
|
content string |
|
mac hash.Hash |
|
signature string |
|
) |
|
content = fmt.Sprintf("%s\n%s\n\n%d\n", method, bucket, expire) |
|
mac = hmac.New(sha1.New, []byte(secret)) |
|
mac.Write([]byte(content)) |
|
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil)) |
|
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire) |
|
return |
|
} |
|
|
|
// EditTimes count times of article edited. |
|
func (d *Dao) EditTimes(c context.Context, id int64) (count int, err error) { |
|
var sqlStr = fmt.Sprintf(_countEditTimesSQL, d.hit(id)) |
|
row := d.articleDB.QueryRow(c, sqlStr, id) |
|
if err = row.Scan(&count); err != nil { |
|
if err == sql.ErrNoRows { |
|
err = nil |
|
return |
|
} |
|
PromError("db:EditTimes") |
|
log.Error("dao.EditTimes error(%+v)", err) |
|
} |
|
return |
|
} |
|
|
|
// ArticleVersion . |
|
func (d *Dao) ArticleVersion(c context.Context, aid int64) (a *artmdl.Article, err error) { |
|
var ( |
|
extStr string |
|
extMsg artmdl.ExtMsg |
|
imageURLs, originURLs string |
|
) |
|
row := d.articleDB.QueryRow(c, _articleVersionSQL, aid) |
|
a = &artmdl.Article{ |
|
Meta: &artmdl.Meta{ |
|
Media: &artmdl.Media{}, |
|
Category: &artmdl.Category{}, |
|
List: &artmdl.List{}, |
|
}, |
|
} |
|
if err = row.Scan(&a.ID, &a.Category.ID, &a.Title, &a.State, &a.Content, &a.Summary, &a.BannerURL, &a.TemplateID, &a.Reprint, &imageURLs, &a.Attributes, &a.Words, &a.Dynamic, &originURLs, &a.Media.MediaID, &a.Media.Spoiler, &a.ApplyTime, &extStr); err != nil { |
|
log.Error("dao.ArticleHistory.Scan error(%+v)", err) |
|
return |
|
} |
|
if err = json.Unmarshal([]byte(extStr), &extMsg); err != nil { |
|
log.Error("dao.ArticleHistory.Unmarshal error(%+v)", err) |
|
return |
|
} |
|
a.ImageURLs = strings.Split(imageURLs, ",") |
|
a.OriginImageURLs = strings.Split(originURLs, ",") |
|
a.BannerURL = artmdl.CompleteURL(a.BannerURL) |
|
a.ImageURLs = artmdl.CompleteURLs(a.ImageURLs) |
|
a.OriginImageURLs = artmdl.CompleteURLs(a.OriginImageURLs) |
|
a.Tags = extMsg.Tags |
|
return |
|
} |
|
|
|
// LastReason return last reason from article_versions by aid and state. |
|
func (d *Dao) LastReason(c context.Context, id int64, state int32) (res string, err error) { |
|
if err = d.articleDB.QueryRow(c, _reasonOfVersion, id, state).Scan(&res); err != nil { |
|
if err == sql.ErrNoRows { |
|
err = nil |
|
return |
|
} |
|
PromError("db:LastReason") |
|
log.Error("dao.LastReason(%s) error(%+v)", _reasonOfVersion, err) |
|
} |
|
return |
|
}
|
|
|