like.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. package like
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "strconv"
  9. "time"
  10. "go-common/app/interface/main/activity/model/like"
  11. "go-common/library/cache/memcache"
  12. "go-common/library/cache/redis"
  13. "go-common/library/database/elastic"
  14. "go-common/library/database/sql"
  15. "go-common/library/ecode"
  16. "go-common/library/log"
  17. "go-common/library/net/metadata"
  18. xtime "go-common/library/time"
  19. "go-common/library/xstr"
  20. "github.com/pkg/errors"
  21. )
  22. const (
  23. _selLikeSQL = "SELECT id,wid FROM likes where state = 1 AND sid = ? ORDER BY type"
  24. _likeSQL = "SELECT id,sid,type,mid,wid,state,stick_top,ctime,mtime FROM likes WHERE id = ? and state = 1"
  25. _likeMoreLidSQL = "SELECT id,sid,type,mid,wid,state,stick_top,ctime,mtime FROM likes WHERE id > ? order by id asc limit 1000"
  26. _likesBySidSQL = "SELECT id,sid,type,mid,wid,state,stick_top,ctime,mtime FROM likes WHERE id > ? and sid = ? and state = 1 order by id asc limit 1000"
  27. _likesSQL = "SELECT id,sid,type,mid,wid,state,stick_top,ctime,mtime FROM likes WHERE id IN (%s) and state = 1"
  28. _likeListSQL = "SELECT id,wid,ctime FROM likes WHERE state = 1 AND sid = ? ORDER BY id DESC"
  29. _likeMaxIDSQL = "SELECT id FROM likes ORDER BY id DESC limit 1"
  30. _keyLikeTagFmt = "l_t_%d_%d"
  31. _keyLikeTagCntsFmt = "l_t_cs_%d"
  32. _keyLikeRegionFmt = "l_r_%d_%d"
  33. // likeAPI ip frequence key the old is ddos:like:ip:%s
  34. _keyIPRequestFmt = "go:ddos:l:ip:%s"
  35. // the cache set of like order by ctime the old is bilibili-activity:ctime:%d
  36. _keyLikeListCtimeFmt = "go:bl-a:ctime:%d"
  37. _keyLikeListRandomFmt = "go:bl-a:random:%d"
  38. // the cache set of like type order by ctime
  39. _keyLikeListTypeCtimeFmt = "go:b:a:t:%d:%d"
  40. // storyKing LikeAct cache
  41. _keyStoryDilyLikeFmt = "go:s:d:m:%s:%d:%d"
  42. // storyKing each likeAct cahce
  43. _keyStoryEachLikeFmt = "go:s:ea:m:%s:%d:%d:%d"
  44. // es index
  45. _activity = "activity"
  46. // EsOrderLikes archive center likes.
  47. EsOrderLikes = "likes"
  48. // EsOrderCoin archive center coin .
  49. EsOrderCoin = "coin"
  50. // EsOrderReply archive center reply.
  51. EsOrderReply = "reply"
  52. // EsOrderShare archive center share.
  53. EsOrderShare = "share"
  54. // EsOrderClick archive center click
  55. EsOrderClick = "click"
  56. // EsOrderDm archive center dm
  57. EsOrderDm = "dm"
  58. // EsOrderFav archive center fav
  59. EsOrderFav = "fav"
  60. // ActOrderLike activity list like order.
  61. ActOrderLike = "like"
  62. // ActOrderCtime activity list ctime order.
  63. ActOrderCtime = "ctime"
  64. // ActOrderRandom order random .
  65. ActOrderRandom = "random"
  66. )
  67. // ipRequestKey .
  68. func ipRequestKey(ip string) string {
  69. return fmt.Sprintf(_keyIPRequestFmt, ip)
  70. }
  71. func likeListCtimeKey(sid int64) string {
  72. return fmt.Sprintf(_keyLikeListCtimeFmt, sid)
  73. }
  74. func likeListRandomKey(sid int64) string {
  75. return fmt.Sprintf(_keyLikeListRandomFmt, sid)
  76. }
  77. func likeListTypeCtimeKey(types int, sid int64) string {
  78. return fmt.Sprintf(_keyLikeListTypeCtimeFmt, types, sid)
  79. }
  80. func keyLikeTag(sid, tagID int64) string {
  81. return fmt.Sprintf(_keyLikeTagFmt, sid, tagID)
  82. }
  83. func keyLikeTagCounts(sid int64) string {
  84. return fmt.Sprintf(_keyLikeTagCntsFmt, sid)
  85. }
  86. func keyLikeRegion(sid int64, regionID int16) string {
  87. return fmt.Sprintf(_keyLikeRegionFmt, sid, regionID)
  88. }
  89. func keyStoryLikeKey(sid, mid int64, daily string) string {
  90. return fmt.Sprintf(_keyStoryDilyLikeFmt, daily, sid, mid)
  91. }
  92. func keyStoryEachLike(sid, mid, lid int64, daily string) string {
  93. return fmt.Sprintf(_keyStoryEachLikeFmt, daily, sid, mid, lid)
  94. }
  95. // LikeTypeList dao sql.
  96. func (dao *Dao) LikeTypeList(c context.Context, sid int64) (ns []*like.Like, err error) {
  97. rows, err := dao.db.Query(c, _selLikeSQL, sid)
  98. if err != nil {
  99. log.Error("LikeTypeList dao.db.Query error(%v)", err)
  100. return
  101. }
  102. ns = make([]*like.Like, 0)
  103. defer rows.Close()
  104. for rows.Next() {
  105. n := &like.Like{}
  106. if err = rows.Scan(&n.ID, &n.Wid); err != nil {
  107. log.Error("row.Scan error(%v)", err)
  108. return
  109. }
  110. ns = append(ns, n)
  111. }
  112. if err = rows.Err(); err != nil {
  113. log.Error("row.Scan row error(%v)", err)
  114. }
  115. return
  116. }
  117. // LikeList dao sql
  118. func (dao *Dao) LikeList(c context.Context, sid int64) (ns []*like.Item, err error) {
  119. rows, err := dao.db.Query(c, _likeListSQL, sid)
  120. if err != nil {
  121. log.Error("LikeList dao.db.Query error(%v)", err)
  122. return
  123. }
  124. defer rows.Close()
  125. for rows.Next() {
  126. n := new(like.Item)
  127. if err = rows.Scan(&n.ID, &n.Wid, &n.Ctime); err != nil {
  128. log.Error("row.Scan error(%v)", err)
  129. return
  130. }
  131. ns = append(ns, n)
  132. }
  133. if err = rows.Err(); err != nil {
  134. log.Error("row.Scan row error(%v)", err)
  135. }
  136. return
  137. }
  138. // RawLikes get likes by wid.
  139. func (dao *Dao) RawLikes(c context.Context, ids []int64) (data map[int64]*like.Item, err error) {
  140. rows, err := dao.db.Query(c, fmt.Sprintf(_likesSQL, xstr.JoinInts(ids)))
  141. if err != nil {
  142. log.Error("Likes dao.db.Query error(%v)", err)
  143. return
  144. }
  145. defer rows.Close()
  146. data = make(map[int64]*like.Item)
  147. for rows.Next() {
  148. res := &like.Item{}
  149. if err = rows.Scan(&res.ID, &res.Sid, &res.Type, &res.Mid, &res.Wid, &res.State, &res.StickTop, &res.Ctime, &res.Mtime); err != nil {
  150. log.Error("Likes row.Scan error(%v)", err)
  151. return
  152. }
  153. data[res.ID] = res
  154. }
  155. if err = rows.Err(); err != nil {
  156. log.Error("Likes row.Scan row error(%v)", err)
  157. }
  158. return
  159. }
  160. // LikeTagCache get like tag cache.
  161. func (dao *Dao) LikeTagCache(c context.Context, sid, tagID int64, start, end int) (likes []*like.Item, err error) {
  162. var values []interface{}
  163. key := keyLikeTag(sid, tagID)
  164. conn := dao.redis.Get(c)
  165. defer conn.Close()
  166. if values, err = redis.Values(conn.Do("ZREVRANGE", key, start, end)); err != nil {
  167. log.Error("LikeTagCache conn.Do(ZREVRANGE, %s) error(%v)", key, err)
  168. return
  169. } else if len(values) == 0 {
  170. return
  171. }
  172. for len(values) > 0 {
  173. var bs []byte
  174. if values, err = redis.Scan(values, &bs); err != nil {
  175. log.Error("LikeRegionCache redis.Scan(%v) error(%v)", values, err)
  176. return
  177. }
  178. like := new(like.Item)
  179. if err = json.Unmarshal(bs, &like); err != nil {
  180. log.Error("LikeRegionCache conn.Do(ZRANGE, %s) error(%v)", key, err)
  181. continue
  182. }
  183. if like.ID > 0 {
  184. likes = append(likes, like)
  185. }
  186. }
  187. return
  188. }
  189. // LikeTagCnt get like tag cnt.
  190. func (dao *Dao) LikeTagCnt(c context.Context, sid, tagID int64) (count int, err error) {
  191. key := keyLikeTag(sid, tagID)
  192. conn := dao.redis.Get(c)
  193. defer conn.Close()
  194. if count, err = redis.Int(conn.Do("ZCARD", key)); err != nil {
  195. log.Error("LikeRegionCnt conn.Do(ZCARD, %s) error(%v)", key, err)
  196. }
  197. return
  198. }
  199. // SetLikeTagCache set like tag cache no expire.
  200. func (dao *Dao) SetLikeTagCache(c context.Context, sid, tagID int64, likes []*like.Item) (err error) {
  201. var bs []byte
  202. key := keyLikeTag(sid, tagID)
  203. conn := dao.redis.Get(c)
  204. defer conn.Close()
  205. if err = conn.Send("DEL", key); err != nil {
  206. log.Error("SetLikeTagCache conn.Send(DEL, %s) error(%v)", key, err)
  207. return
  208. }
  209. args := redis.Args{}.Add(key)
  210. for _, v := range likes {
  211. if bs, err = json.Marshal(v); err != nil {
  212. log.Error("SetLikeTagCache json.Marshal() error(%v)", err)
  213. return
  214. }
  215. args = args.Add(v.Ctime).Add(bs)
  216. }
  217. if err = conn.Send("ZADD", args...); err != nil {
  218. log.Error("conn.Send(ZADD, %s) error(%v)", key, err)
  219. return
  220. }
  221. if err = conn.Flush(); err != nil {
  222. log.Error("conn.Flush error(%v)", err)
  223. return
  224. }
  225. for i := 0; i < 2; i++ {
  226. if _, err = conn.Receive(); err != nil {
  227. log.Error("conn.Receive() error(%v)", err)
  228. return
  229. }
  230. }
  231. return
  232. }
  233. // LikeRegionCache get like region cache.
  234. func (dao *Dao) LikeRegionCache(c context.Context, sid int64, regionID int16, start, end int) (likes []*like.Item, err error) {
  235. var values []interface{}
  236. key := keyLikeRegion(sid, regionID)
  237. conn := dao.redis.Get(c)
  238. defer conn.Close()
  239. if values, err = redis.Values(conn.Do("ZREVRANGE", key, start, end)); err != nil {
  240. log.Error("LikeRegionCache conn.Do(ZREVRANGE, %s) error(%v)", key, err)
  241. return
  242. } else if len(values) == 0 {
  243. return
  244. }
  245. for len(values) > 0 {
  246. var bs []byte
  247. if values, err = redis.Scan(values, &bs); err != nil {
  248. log.Error("LikeRegionCache redis.Scan(%v) error(%v)", values, err)
  249. return
  250. }
  251. like := new(like.Item)
  252. if err = json.Unmarshal(bs, &like); err != nil {
  253. log.Error("LikeRegionCache conn.Do(ZREVRANGE, %s) error(%v)", key, err)
  254. continue
  255. }
  256. if like.ID > 0 {
  257. likes = append(likes, like)
  258. }
  259. }
  260. return
  261. }
  262. // LikeRegionCnt get like region cnt.
  263. func (dao *Dao) LikeRegionCnt(c context.Context, sid int64, regionID int16) (count int, err error) {
  264. key := keyLikeRegion(sid, regionID)
  265. conn := dao.redis.Get(c)
  266. defer conn.Close()
  267. if count, err = redis.Int(conn.Do("ZCARD", key)); err != nil {
  268. log.Error("LikeRegionCnt conn.Do(ZCARD, %s) error(%v)", key, err)
  269. }
  270. return
  271. }
  272. // SetLikeRegionCache set like region cache.
  273. func (dao *Dao) SetLikeRegionCache(c context.Context, sid int64, regionID int16, likes []*like.Item) (err error) {
  274. var bs []byte
  275. key := keyLikeRegion(sid, regionID)
  276. conn := dao.redis.Get(c)
  277. defer conn.Close()
  278. if err = conn.Send("DEL", key); err != nil {
  279. log.Error("SetLikeTagCache conn.Send(DEL, %s) error(%v)", key, err)
  280. return
  281. }
  282. args := redis.Args{}.Add(key)
  283. for _, v := range likes {
  284. if bs, err = json.Marshal(v); err != nil {
  285. log.Error("SetLikeRegionCache json.Marshal() error(%v)", err)
  286. return
  287. }
  288. args = args.Add(v.Ctime).Add(bs)
  289. }
  290. if err = conn.Send("ZADD", args...); err != nil {
  291. log.Error("conn.Send(ZADD, %s) error(%v)", key, err)
  292. return
  293. }
  294. if err = conn.Flush(); err != nil {
  295. log.Error("conn.Flush error(%v)", err)
  296. return
  297. }
  298. for i := 0; i < 2; i++ {
  299. if _, err = conn.Receive(); err != nil {
  300. log.Error("conn.Receive() error(%v)", err)
  301. return
  302. }
  303. }
  304. return
  305. }
  306. // SetTagLikeCountsCache .
  307. func (dao *Dao) SetTagLikeCountsCache(c context.Context, sid int64, counts map[int64]int32) (err error) {
  308. key := keyLikeTagCounts(sid)
  309. conn := dao.redis.Get(c)
  310. defer conn.Close()
  311. args := redis.Args{}.Add(key)
  312. for tagID, count := range counts {
  313. args = args.Add(tagID).Add(count)
  314. }
  315. if _, err = conn.Do("HMSET", args...); err != nil {
  316. log.Error("SetLikeCountsCache conn.Do(HMSET) key(%s) error(%v)", key, err)
  317. }
  318. return
  319. }
  320. // TagLikeCountsCache get tag like counts cache.
  321. func (dao *Dao) TagLikeCountsCache(c context.Context, sid int64, tagIDs []int64) (counts map[int64]int32, err error) {
  322. if len(tagIDs) == 0 {
  323. return
  324. }
  325. key := keyLikeTagCounts(sid)
  326. conn := dao.redis.Get(c)
  327. defer conn.Close()
  328. args := redis.Args{}.Add(key).AddFlat(tagIDs)
  329. var tmpCounts []int
  330. if tmpCounts, err = redis.Ints(conn.Do("HMGET", args...)); err != nil {
  331. log.Error("redis.Ints(HMGET) key(%s) args(%v) error(%v)", key, args, err)
  332. return
  333. }
  334. if len(tmpCounts) != len(tagIDs) {
  335. return
  336. }
  337. counts = make(map[int64]int32, len(tagIDs))
  338. for i, tagID := range tagIDs {
  339. counts[tagID] = int32(tmpCounts[i])
  340. }
  341. return
  342. }
  343. // RawLike get like by id .
  344. func (dao *Dao) RawLike(c context.Context, id int64) (res *like.Item, err error) {
  345. res = new(like.Item)
  346. row := dao.db.QueryRow(c, _likeSQL, id)
  347. if err = row.Scan(&res.ID, &res.Sid, &res.Type, &res.Mid, &res.Wid, &res.State, &res.StickTop, &res.Ctime, &res.Mtime); err != nil {
  348. if err == sql.ErrNoRows {
  349. err = nil
  350. } else {
  351. err = errors.Wrap(err, "LikeByID:QueryRow")
  352. }
  353. }
  354. return
  355. }
  356. // LikeListMoreLid get likes data with like.id greater than lid
  357. func (dao *Dao) LikeListMoreLid(c context.Context, lid int64) (res []*like.Item, err error) {
  358. var rows *sql.Rows
  359. if rows, err = dao.db.Query(c, _likeMoreLidSQL, lid); err != nil {
  360. if err == sql.ErrNoRows {
  361. err = nil
  362. } else {
  363. err = errors.Wrap(err, "LikeListMoreLid:dao.db.Query()")
  364. }
  365. return
  366. }
  367. defer rows.Close()
  368. res = make([]*like.Item, 0, 1000)
  369. for rows.Next() {
  370. a := &like.Item{}
  371. if err = rows.Scan(&a.ID, &a.Sid, &a.Type, &a.Mid, &a.Wid, &a.State, &a.StickTop, &a.Ctime, &a.Mtime); err != nil {
  372. err = errors.Wrap(err, "LikeListMoreLid:rows.Scan()")
  373. return
  374. }
  375. res = append(res, a)
  376. }
  377. if err = rows.Err(); err != nil {
  378. err = errors.Wrap(err, "LikeListMoreLid: rows.Err()")
  379. }
  380. return
  381. }
  382. // LikesBySid get sid all likes .
  383. func (dao *Dao) LikesBySid(c context.Context, lid, sid int64) (res []*like.Item, err error) {
  384. var rows *sql.Rows
  385. if rows, err = dao.db.Query(c, _likesBySidSQL, lid, sid); err != nil {
  386. if err == sql.ErrNoRows {
  387. err = nil
  388. } else {
  389. err = errors.Wrap(err, "LikesBySid:dao.db.Query()")
  390. }
  391. return
  392. }
  393. defer rows.Close()
  394. res = make([]*like.Item, 0, 1000)
  395. for rows.Next() {
  396. a := &like.Item{}
  397. if err = rows.Scan(&a.ID, &a.Sid, &a.Type, &a.Mid, &a.Wid, &a.State, &a.StickTop, &a.Ctime, &a.Mtime); err != nil {
  398. err = errors.Wrap(err, "LikesBySid:rows.Scan()")
  399. return
  400. }
  401. res = append(res, a)
  402. }
  403. if err = rows.Err(); err != nil {
  404. err = errors.Wrap(err, "LikesBySid:rows.Err()")
  405. }
  406. return
  407. }
  408. // IPReqquestCheck check ip has ben used or not .
  409. func (dao *Dao) IPReqquestCheck(c context.Context, ip string) (val int, err error) {
  410. var (
  411. mcKey = ipRequestKey(ip)
  412. conn = dao.mc.Get(c)
  413. item *memcache.Item
  414. )
  415. defer conn.Close()
  416. if item, err = conn.Get(mcKey); err != nil {
  417. if err == memcache.ErrNotFound {
  418. err = nil
  419. val = 0
  420. } else {
  421. err = errors.Wrap(err, "IPReqquestCheck:conn.Get() error")
  422. }
  423. return
  424. }
  425. if err = conn.Scan(item, &val); err != nil {
  426. err = errors.Wrap(err, "IPReqquestCheck:conn.Scan() ")
  427. }
  428. return
  429. }
  430. // SetIPRequest set ip has been used
  431. func (dao *Dao) SetIPRequest(c context.Context, ip string) (err error) {
  432. var (
  433. conn = dao.mc.Get(c)
  434. item = &memcache.Item{
  435. Key: ipRequestKey(ip),
  436. Expiration: dao.mcLikeIPExpire,
  437. Flags: memcache.FlagRAW,
  438. Value: []byte("1"),
  439. }
  440. )
  441. defer conn.Close()
  442. if err = conn.Set(item); err != nil {
  443. err = errors.Wrap(err, "SetIPRequest:conn.Set()")
  444. }
  445. return
  446. }
  447. // LikeCtime .
  448. func (dao *Dao) LikeCtime(c context.Context, sid int64, start, end int) (res []int64, err error) {
  449. var (
  450. conn = dao.redis.Get(c)
  451. key = likeListCtimeKey(sid)
  452. )
  453. defer conn.Close()
  454. if res, err = redis.Int64s(conn.Do("ZREVRANGE", key, start, end)); err != nil {
  455. if err == redis.ErrNil {
  456. err = nil
  457. } else {
  458. err = errors.Wrap(err, "conn.Do(ZREVRANGE)")
  459. }
  460. }
  461. return
  462. }
  463. // LikeRandom .
  464. func (dao *Dao) LikeRandom(c context.Context, sid int64, start, end int) (res []int64, err error) {
  465. var (
  466. conn = dao.redis.Get(c)
  467. key = likeListRandomKey(sid)
  468. )
  469. defer conn.Close()
  470. if res, err = redis.Int64s(conn.Do("ZREVRANGE", key, start, end)); err != nil {
  471. if err == redis.ErrNil {
  472. err = nil
  473. } else {
  474. err = errors.Wrap(err, "conn.Do(ZREVRANGE)")
  475. }
  476. }
  477. return
  478. }
  479. // LikeRandomCount .
  480. func (dao *Dao) LikeRandomCount(c context.Context, sid int64) (res int64, err error) {
  481. var (
  482. conn = dao.redis.Get(c)
  483. key = likeListRandomKey(sid)
  484. )
  485. defer conn.Close()
  486. if res, err = redis.Int64(conn.Do("ZCARD", key)); err != nil {
  487. log.Error("LikeRandomCount conn.Do(ZCARD, %s) error(%v)", key, err)
  488. }
  489. return
  490. }
  491. // SetLikeRandom .
  492. func (dao *Dao) SetLikeRandom(c context.Context, sid int64, ids []int64) (err error) {
  493. var (
  494. conn = dao.redis.Get(c)
  495. key = likeListRandomKey(sid)
  496. )
  497. defer conn.Close()
  498. if len(ids) == 0 {
  499. return
  500. }
  501. args := redis.Args{}.Add(key)
  502. for k, v := range ids {
  503. args = args.Add(k + 1).Add(v)
  504. }
  505. if err = conn.Send("ZADD", args...); err != nil {
  506. err = errors.Wrap(err, "conn.Send(ZADD)")
  507. return
  508. }
  509. if err = conn.Send("EXPIRE", key, dao.randomExpire); err != nil {
  510. err = errors.Wrap(err, "conn.Send(EXPIRE)")
  511. return
  512. }
  513. if err = conn.Flush(); err != nil {
  514. err = errors.Wrap(err, "conn.Flush()")
  515. return
  516. }
  517. for i := 0; i < 2; i++ {
  518. if _, err = conn.Receive(); err != nil {
  519. err = errors.Wrapf(err, "conn.Receive(%d)", i)
  520. return
  521. }
  522. }
  523. return
  524. }
  525. // LikeCount .
  526. func (dao *Dao) LikeCount(c context.Context, sid int64) (res int64, err error) {
  527. var (
  528. conn = dao.redis.Get(c)
  529. key = likeListCtimeKey(sid)
  530. )
  531. defer conn.Close()
  532. if res, err = redis.Int64(conn.Do("ZCARD", key)); err != nil {
  533. log.Error("LikeCount conn.Do(ZCARD, %s) error(%v)", key, err)
  534. }
  535. return
  536. }
  537. // LikeListCtime set like list by ctime.
  538. func (dao *Dao) LikeListCtime(c context.Context, sid int64, items []*like.Item) (err error) {
  539. var (
  540. conn = dao.redis.Get(c)
  541. key = likeListCtimeKey(sid)
  542. max = 0
  543. )
  544. defer conn.Close()
  545. args := redis.Args{}.Add(key)
  546. for _, v := range items {
  547. args = args.Add(v.Ctime).Add(v.ID)
  548. if v.Type != 0 {
  549. typeKey := likeListTypeCtimeKey(v.Type, sid)
  550. typeArgs := redis.Args{}.Add(typeKey).Add(v.Ctime).Add(v.ID)
  551. if err = conn.Send("ZADD", typeArgs...); err != nil {
  552. log.Error("LikeListCtime:conn.Send(%v) error(%v)", v, err)
  553. return
  554. }
  555. max++
  556. }
  557. }
  558. if err = conn.Send("ZADD", args...); err != nil {
  559. log.Error("LikeListCtime:conn.Send(%v) error(%v)", items, err)
  560. return
  561. }
  562. max++
  563. if err = conn.Flush(); err != nil {
  564. log.Error("LikeListCtime:conn.Flush error(%v)", err)
  565. return
  566. }
  567. for i := 0; i < max; i++ {
  568. if _, err = conn.Receive(); err != nil {
  569. log.Error("LikeListCtime:conn.Receive(%d) error(%v)", i, err)
  570. return
  571. }
  572. }
  573. return
  574. }
  575. //DelLikeListCtime delete likeList Ctime cache .
  576. func (dao *Dao) DelLikeListCtime(c context.Context, sid int64, items []*like.Item) (err error) {
  577. var (
  578. conn = dao.redis.Get(c)
  579. key = likeListCtimeKey(sid)
  580. max = 0
  581. )
  582. defer conn.Close()
  583. args := redis.Args{}.Add(key)
  584. for _, v := range items {
  585. args = args.Add(v.ID)
  586. if v.Type != 0 {
  587. typeKey := likeListTypeCtimeKey(v.Type, sid)
  588. if err = conn.Send("ZREM", typeKey, v.ID); err != nil {
  589. log.Error("DelLikeListCtime:conn.Send(%v) error(%v)", v, err)
  590. return
  591. }
  592. max++
  593. }
  594. }
  595. if err = conn.Send("ZREM", args...); err != nil {
  596. log.Error("DelLikeListCtime:conn.Send(%v) error(%v)", args, err)
  597. return
  598. }
  599. max++
  600. if err = conn.Flush(); err != nil {
  601. log.Error("DelLikeListCtime:conn.Flush error(%v)", err)
  602. return
  603. }
  604. for i := 0; i < max; i++ {
  605. if _, err = conn.Receive(); err != nil {
  606. log.Error("DelLikeListCtime:conn.Receive(%d) error(%v)", i, err)
  607. return
  608. }
  609. }
  610. return
  611. }
  612. // LikeMaxID get likes last id .
  613. func (dao *Dao) LikeMaxID(c context.Context) (res *like.Item, err error) {
  614. res = new(like.Item)
  615. rows := dao.db.QueryRow(c, _likeMaxIDSQL)
  616. if err = rows.Scan(&res.ID); err != nil {
  617. if err == sql.ErrNoRows {
  618. err = nil
  619. } else {
  620. err = errors.Wrap(err, "LikeMaxID:QueryRow")
  621. }
  622. }
  623. return
  624. }
  625. // GroupItemData like data.
  626. func (dao *Dao) GroupItemData(c context.Context, sid int64, ck string) (data []*like.GroupItem, err error) {
  627. var req *http.Request
  628. if req, err = dao.client.NewRequest(http.MethodGet, fmt.Sprintf(dao.likeItemURL, sid), metadata.String(c, metadata.RemoteIP), url.Values{}); err != nil {
  629. return
  630. }
  631. req.Header.Set("Cookie", ck)
  632. var res struct {
  633. Code int `json:"code"`
  634. Data struct {
  635. List []*like.GroupItem `json:"list"`
  636. } `json:"data"`
  637. }
  638. if err = dao.client.Do(c, req, &res, dao.likeItemURL); err != nil {
  639. err = errors.Wrapf(err, "LikeData dao.client.Do sid(%d)", sid)
  640. return
  641. }
  642. if res.Code != ecode.OK.Code() {
  643. err = errors.Wrapf(ecode.Int(res.Code), "LikeData sid(%d)", sid)
  644. return
  645. }
  646. data = res.Data.List
  647. return
  648. }
  649. // RawSourceItemData get source data.
  650. func (dao *Dao) RawSourceItemData(c context.Context, sid int64) (sids []int64, err error) {
  651. var res struct {
  652. Code int `json:"code"`
  653. Data struct {
  654. List []*struct {
  655. Data struct {
  656. Sid string `json:"sid"`
  657. } `json:"data"`
  658. } `json:"list"`
  659. } `json:"data"`
  660. }
  661. if err = dao.client.RESTfulGet(c, dao.sourceItemURL, metadata.String(c, metadata.RemoteIP), url.Values{}, &res, sid); err != nil {
  662. err = errors.Wrapf(err, "LikeData dao.client.RESTfulGet sid(%d)", sid)
  663. return
  664. }
  665. if res.Code != ecode.OK.Code() {
  666. err = errors.Wrapf(ecode.Int(res.Code), "LikeData sid(%d)", sid)
  667. return
  668. }
  669. for _, v := range res.Data.List {
  670. if sid, e := strconv.ParseInt(v.Data.Sid, 10, 64); e != nil {
  671. continue
  672. } else {
  673. sids = append(sids, sid)
  674. }
  675. }
  676. return
  677. }
  678. // SourceItem get source data json raw message.
  679. func (dao *Dao) SourceItem(c context.Context, sid int64) (source json.RawMessage, err error) {
  680. var res struct {
  681. Code int `json:"code"`
  682. Data json.RawMessage `json:"data"`
  683. }
  684. if err = dao.client.RESTfulGet(c, dao.sourceItemURL, metadata.String(c, metadata.RemoteIP), url.Values{}, &res, sid); err != nil {
  685. err = errors.Wrapf(err, "LikeData dao.client.RESTfulGet sid(%d)", sid)
  686. return
  687. }
  688. if res.Code != ecode.OK.Code() {
  689. err = errors.Wrapf(ecode.Int(res.Code), "LikeData sid(%d)", sid)
  690. return
  691. }
  692. source = res.Data
  693. return
  694. }
  695. // StoryLikeSum .
  696. func (dao *Dao) StoryLikeSum(c context.Context, sid, mid int64) (res int64, err error) {
  697. var (
  698. conn = dao.redis.Get(c)
  699. now = time.Now().Format("2006-01-02")
  700. key = keyStoryLikeKey(sid, mid, now)
  701. )
  702. defer conn.Close()
  703. if res, err = redis.Int64(conn.Do("GET", key)); err != nil {
  704. if err == redis.ErrNil {
  705. err = nil
  706. res = -1
  707. } else {
  708. err = errors.Wrap(err, "redis.Do(get)")
  709. }
  710. }
  711. return
  712. }
  713. // IncrStoryLikeSum .
  714. func (dao *Dao) IncrStoryLikeSum(c context.Context, sid, mid int64, score int64) (res int64, err error) {
  715. var (
  716. conn = dao.redis.Get(c)
  717. now = time.Now().Format("2006-01-02")
  718. key = keyStoryLikeKey(sid, mid, now)
  719. )
  720. defer conn.Close()
  721. if res, err = redis.Int64(conn.Do("INCRBY", key, score)); err != nil {
  722. err = errors.Wrap(err, "redis.Do(get)")
  723. }
  724. return
  725. }
  726. // SetLikeSum .
  727. func (dao *Dao) SetLikeSum(c context.Context, sid, mid int64, sum int64) (err error) {
  728. var (
  729. conn = dao.redis.Get(c)
  730. now = time.Now().Format("2006-01-02")
  731. key = keyStoryLikeKey(sid, mid, now)
  732. res bool
  733. )
  734. defer conn.Close()
  735. if res, err = redis.Bool(conn.Do("SETNX", key, sum)); err != nil {
  736. err = errors.Wrap(err, "redis.Bool(SETNX)")
  737. return
  738. }
  739. if res {
  740. conn.Do("EXPIRE", key, 86400)
  741. } else {
  742. err = errors.New("redis.Bool(SETNX) res false")
  743. }
  744. return
  745. }
  746. // StoryEachLikeSum .
  747. func (dao *Dao) StoryEachLikeSum(c context.Context, sid, mid, lid int64) (res int64, err error) {
  748. var (
  749. conn = dao.redis.Get(c)
  750. now = time.Now().Format("2006-01-02")
  751. key = keyStoryEachLike(sid, mid, lid, now)
  752. )
  753. defer conn.Close()
  754. if res, err = redis.Int64(conn.Do("GET", key)); err != nil {
  755. if err == redis.ErrNil {
  756. err = nil
  757. res = -1
  758. } else {
  759. err = errors.Wrap(err, "redis.Do(get)")
  760. }
  761. }
  762. return
  763. }
  764. // IncrStoryEachLikeAct .
  765. func (dao *Dao) IncrStoryEachLikeAct(c context.Context, sid, mid, lid int64, score int64) (res int64, err error) {
  766. var (
  767. conn = dao.redis.Get(c)
  768. now = time.Now().Format("2006-01-02")
  769. key = keyStoryEachLike(sid, mid, lid, now)
  770. )
  771. defer conn.Close()
  772. if res, err = redis.Int64(conn.Do("INCRBY", key, score)); err != nil {
  773. err = errors.Wrap(err, "redis.Do(get)")
  774. }
  775. return
  776. }
  777. // SetEachLikeSum .
  778. func (dao *Dao) SetEachLikeSum(c context.Context, sid, mid, lid int64, sum int64) (err error) {
  779. var (
  780. conn = dao.redis.Get(c)
  781. now = time.Now().Format("2006-01-02")
  782. key = keyStoryEachLike(sid, mid, lid, now)
  783. res bool
  784. )
  785. defer conn.Close()
  786. if res, err = redis.Bool(conn.Do("SETNX", key, sum)); err != nil {
  787. err = errors.Wrap(err, "redis.Bool(SETNX)")
  788. return
  789. }
  790. if res {
  791. conn.Do("EXPIRE", key, 86400)
  792. } else {
  793. err = errors.New("redis.Bool(SETNX) res false")
  794. }
  795. return
  796. }
  797. // ListFromES .
  798. func (dao *Dao) ListFromES(c context.Context, sid int64, order string, ps, pn int, seed int64) (res *like.ListInfo, err error) {
  799. actResult := new(struct {
  800. Result []struct {
  801. ID int64 `json:"id"`
  802. Wid int64 `json:"wid"`
  803. Ctime xtime.Time `json:"ctime"`
  804. Sid int64 `json:"sid"`
  805. Type int `json:"type"`
  806. Mid int64 `json:"mid"`
  807. State int `json:"state"`
  808. Mtime xtime.Time `json:"mtime"`
  809. Likes int64 `json:"likes"`
  810. Click int64 `json:"click"`
  811. Coin int64 `json:"coin"`
  812. Share int64 `json:"share"`
  813. Reply int64 `json:"reply"`
  814. Dm int64 `json:"dm"`
  815. Fav int64 `json:"fav"`
  816. } `json:"result"`
  817. Page *like.Page `json:"page"`
  818. })
  819. req := dao.es.NewRequest(_activity).Index(_activity).WhereEq("sid", sid).WhereEq("state", 1).Ps(ps).Pn(pn)
  820. if order != "" {
  821. req.Order(order, elastic.OrderDesc)
  822. }
  823. if seed > 0 {
  824. req.OrderRandomSeed(time.Unix(seed, 0).Format("2006-01-02 15:04:05"))
  825. }
  826. req.Fields("id", "sid", "wid", "mid", "type", "ctime", "mtime", "state", "click", "likes", "coin", "share", "reply", "dm", "fav")
  827. if err = req.Scan(c, &actResult); err != nil {
  828. err = errors.Wrap(err, "req.Scan")
  829. return
  830. }
  831. if len(actResult.Result) == 0 {
  832. return
  833. }
  834. res = &like.ListInfo{Page: actResult.Page, List: make([]*like.List, 0, len(actResult.Result))}
  835. for _, v := range actResult.Result {
  836. a := &like.List{
  837. Likes: v.Likes,
  838. Click: v.Click,
  839. Coin: v.Coin,
  840. Share: v.Share,
  841. Reply: v.Reply,
  842. Dm: v.Dm,
  843. Fav: v.Fav,
  844. Item: &like.Item{
  845. ID: v.ID,
  846. Wid: v.Wid,
  847. Ctime: v.Ctime,
  848. Sid: v.Sid,
  849. Type: v.Type,
  850. Mid: v.Mid,
  851. State: v.State,
  852. Mtime: v.Mtime,
  853. },
  854. }
  855. res.List = append(res.List, a)
  856. }
  857. return
  858. }
  859. // MultiTags .
  860. func (dao *Dao) MultiTags(c context.Context, wids []int64) (tagList map[int64][]string, err error) {
  861. if len(wids) == 0 {
  862. return
  863. }
  864. var res struct {
  865. Code int `json:"code"`
  866. Data map[int64][]*like.Tag `json:"data"`
  867. }
  868. params := url.Values{}
  869. params.Set("aids", xstr.JoinInts(wids))
  870. if err = dao.client.Get(c, dao.tagURL, "", params, &res); err != nil {
  871. log.Error("MultiTags:dao.client.Get(%s) error(%+v)", dao.tagURL, err)
  872. return
  873. }
  874. if res.Code != ecode.OK.Code() {
  875. err = ecode.Int(res.Code)
  876. return
  877. }
  878. tagList = make(map[int64][]string, len(res.Data))
  879. for k, v := range res.Data {
  880. if len(v) == 0 {
  881. continue
  882. }
  883. tagList[k] = make([]string, 0, len(v))
  884. for _, val := range v {
  885. tagList[k] = append(tagList[k], val.Name)
  886. }
  887. }
  888. return
  889. }
  890. // OidInfoFromES .
  891. func (dao *Dao) OidInfoFromES(c context.Context, oids []int64, sType int) (res map[int64]*like.Item, err error) {
  892. actResult := new(struct {
  893. Result []struct {
  894. ID int64 `json:"id"`
  895. Wid int64 `json:"wid"`
  896. Ctime xtime.Time `json:"ctime"`
  897. Sid int64 `json:"sid"`
  898. Type int `json:"type"`
  899. Mid int64 `json:"mid"`
  900. State int `json:"state"`
  901. Mtime xtime.Time `json:"mtime"`
  902. Likes int64 `json:"likes"`
  903. Click int64 `json:"click"`
  904. Coin int64 `json:"coin"`
  905. Share int64 `json:"share"`
  906. Reply int64 `json:"reply"`
  907. Dm int64 `json:"dm"`
  908. Fav int64 `json:"fav"`
  909. } `json:"result"`
  910. Page *like.Page `json:"page"`
  911. })
  912. req := dao.es.NewRequest(_activity).Index(_activity).WhereIn("wid", oids).WhereEq("type", sType)
  913. req.Fields("id", "sid", "wid", "mid", "type", "ctime", "mtime", "state")
  914. if err = req.Scan(c, &actResult); err != nil {
  915. err = errors.Wrap(err, "req.Scan")
  916. return
  917. }
  918. if len(actResult.Result) == 0 {
  919. return
  920. }
  921. res = make(map[int64]*like.Item, len(actResult.Result))
  922. for _, v := range actResult.Result {
  923. res[v.Wid] = &like.Item{
  924. ID: v.ID,
  925. Wid: v.Wid,
  926. Ctime: v.Ctime,
  927. Sid: v.Sid,
  928. Type: v.Type,
  929. Mid: v.Mid,
  930. State: v.State,
  931. Mtime: v.Mtime,
  932. }
  933. }
  934. return
  935. }