service.go 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150
  1. package like
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "math"
  7. "math/rand"
  8. "net"
  9. "strconv"
  10. "time"
  11. "go-common/app/interface/main/activity/conf"
  12. "go-common/app/interface/main/activity/dao/bnj"
  13. "go-common/app/interface/main/activity/dao/like"
  14. bnjmdl "go-common/app/interface/main/activity/model/bnj"
  15. l "go-common/app/interface/main/activity/model/like"
  16. tagrpc "go-common/app/interface/main/tag/rpc/client"
  17. accapi "go-common/app/service/main/account/api"
  18. arccli "go-common/app/service/main/archive/api"
  19. arcrpc "go-common/app/service/main/archive/api/gorpc"
  20. arcmdl "go-common/app/service/main/archive/model/archive"
  21. coinrpc "go-common/app/service/main/coin/api/gorpc"
  22. spymdl "go-common/app/service/main/spy/model"
  23. spyrpc "go-common/app/service/main/spy/rpc/client"
  24. thumbup "go-common/app/service/main/thumbup/rpc/client"
  25. suitrpc "go-common/app/service/main/usersuit/rpc/client"
  26. "go-common/library/ecode"
  27. "go-common/library/log"
  28. "go-common/library/net/metadata"
  29. "go-common/library/sync/errgroup"
  30. "go-common/library/sync/pipeline/fanout"
  31. xtime "go-common/library/time"
  32. "github.com/pkg/errors"
  33. )
  34. const (
  35. _yes = 1
  36. _no = 0
  37. _typeAll = "all"
  38. _typeRegion = "region"
  39. _like = "like"
  40. _grade = "grade"
  41. _vote = "vote"
  42. _silenceForbid = 1
  43. )
  44. // Service struct
  45. type Service struct {
  46. c *conf.Config
  47. dao *like.Dao
  48. bnjDao *bnj.Dao
  49. arcRPC *arcrpc.Service2
  50. arcClient arccli.ArchiveClient
  51. coin *coinrpc.Service
  52. suit *suitrpc.Service2
  53. accClient accapi.AccountClient
  54. spy *spyrpc.Service
  55. tagRPC *tagrpc.Service
  56. thumbup thumbup.ThumbupRPC
  57. cache *fanout.Fanout
  58. arcType map[int16]*arcmdl.ArcType
  59. dialectTags map[int64]struct{}
  60. dialectRegions map[int16]struct{}
  61. reward map[int]*bnjmdl.Reward
  62. r *rand.Rand
  63. newestSubTs int64
  64. }
  65. // New Service
  66. func New(c *conf.Config) (s *Service) {
  67. s = &Service{
  68. c: c,
  69. cache: fanout.New("cache", fanout.Worker(1), fanout.Buffer(1024)),
  70. dao: like.New(c),
  71. bnjDao: bnj.New(c),
  72. arcRPC: arcrpc.New2(c.RPCClient2.Archive),
  73. coin: coinrpc.New(c.RPCClient2.Coin),
  74. suit: suitrpc.New(c.RPCClient2.Suit),
  75. spy: spyrpc.New(c.RPCClient2.Spy),
  76. tagRPC: tagrpc.New2(c.RPCClient2.Tag),
  77. thumbup: thumbup.New(c.RPCClient2.Thumbup),
  78. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  79. }
  80. var err error
  81. if s.arcClient, err = arccli.NewClient(c.ArcClient); err != nil {
  82. panic(err)
  83. }
  84. if s.accClient, err = accapi.NewClient(c.AccClient); err != nil {
  85. panic(err)
  86. }
  87. s.initDialect()
  88. s.initReward()
  89. go s.arcTypeproc()
  90. go s.actSourceproc()
  91. go s.newestSubTsproc()
  92. return
  93. }
  94. func checkIsLike(subType int64) (likesType bool) {
  95. switch subType {
  96. case l.PICTURELIKE, l.DRAWYOOLIKE, l.TEXTLIKE, l.VIDEOLIKE, l.VIDEO2, l.VIDEO, l.SMALLVIDEO, l.MUSIC, l.PHONEVIDEO, l.STORYKING:
  97. likesType = true
  98. default:
  99. likesType = false
  100. }
  101. return
  102. }
  103. // Subject service
  104. func (s *Service) Subject(c context.Context, sid int64) (res *l.Subject, err error) {
  105. var (
  106. mc = true
  107. subErr error
  108. likeErr error
  109. )
  110. if res, err = s.dao.InfoCache(c, sid); err != nil {
  111. err = nil
  112. mc = false
  113. } else if res != nil {
  114. if res, err = s.LikeArc(c, res); err != nil {
  115. return
  116. }
  117. }
  118. eg, errCtx := errgroup.WithContext(c)
  119. var ls = make([]*l.Like, 0)
  120. eg.Go(func() error {
  121. res, subErr = s.dao.Subject(errCtx, sid)
  122. return subErr
  123. })
  124. eg.Go(func() error {
  125. ls, likeErr = s.dao.LikeTypeList(errCtx, sid)
  126. return likeErr
  127. })
  128. if err = eg.Wait(); err != nil {
  129. log.Error("eg.Wait error(%v)", err)
  130. return
  131. }
  132. if res != nil {
  133. res.List = ls
  134. }
  135. if mc {
  136. err = s.dao.SetInfoCache(c, res, sid)
  137. if err != nil {
  138. log.Error("SetInfoCache error(%v)", err)
  139. }
  140. }
  141. if res, err = s.LikeArc(c, res); err != nil {
  142. return
  143. }
  144. return
  145. }
  146. // LikeArc service
  147. func (s *Service) LikeArc(c context.Context, sub *l.Subject) (res *l.Subject, err error) {
  148. if sub != nil {
  149. if sub.ID == 0 {
  150. res = nil
  151. } else {
  152. res = sub
  153. var (
  154. ok bool
  155. arcs map[int64]*arccli.Arc
  156. aids []int64
  157. )
  158. for _, l := range res.List {
  159. aids = append(aids, l.Wid)
  160. }
  161. argAids := &arcmdl.ArgAids2{
  162. Aids: aids,
  163. }
  164. if arcs, err = s.arcRPC.Archives3(c, argAids); err != nil {
  165. log.Error("s.arcRPC.Archives(arcAids:(%v), arcs), err(%v)", aids, err)
  166. return
  167. }
  168. for _, l := range res.List {
  169. if l.Archive, ok = arcs[l.Wid]; !ok {
  170. log.Info("s.arcs.wid:(%d),ok(%v)", l.Wid, ok)
  171. continue
  172. }
  173. }
  174. }
  175. }
  176. return
  177. }
  178. // OnlineVote Service
  179. func (s *Service) OnlineVote(c context.Context, mid, vote, stage, aid int64) (res bool, err error) {
  180. res = true
  181. if vote != _yes && vote != _no {
  182. err = nil
  183. res = false
  184. return
  185. }
  186. var incrKey string
  187. midStr := strconv.FormatInt(mid, 10)
  188. aidStr := strconv.FormatInt(aid, 10)
  189. stageStr := strconv.FormatInt(stage, 10)
  190. midKye := midStr + ":" + aidStr + ":" + stageStr
  191. if res, err = s.dao.RsSetNX(c, midKye); err != nil {
  192. log.Error("s.OnlineVote.reids(mid:(%v),,vote:(%v),stage:(%v)), err(%v)", mid, vote, stage, err)
  193. return
  194. }
  195. if !res {
  196. return
  197. }
  198. if vote == _yes {
  199. incrKey = aidStr + ":" + stageStr + ":yes"
  200. } else {
  201. incrKey = aidStr + ":" + stageStr + ":no"
  202. }
  203. if mid == 288239 || mid == 26366366 || mid == 20453897 {
  204. log.Info("288239,26366366,20453897")
  205. if res, err = s.dao.Incrby(c, incrKey); err != nil {
  206. log.Error("s.OnlineVote.Incrby(key:(%v)", incrKey)
  207. return
  208. }
  209. } else {
  210. if res, err = s.dao.Incr(c, incrKey); err != nil {
  211. log.Error("s.OnlineVote.Incr(key:(%v)", incrKey)
  212. return
  213. }
  214. }
  215. s.dao.CVoteLog(c, 0, aid, mid, stage, vote)
  216. return
  217. }
  218. // Ltime service
  219. func (s *Service) Ltime(c context.Context, sid int64) (res map[string]interface{}, err error) {
  220. var key = "ltime:" + strconv.FormatInt(sid, 10)
  221. var b []byte
  222. if b, err = s.dao.Rb(c, key); err != nil {
  223. log.Error("s.dao.Rb((%v), err(%v)", key, err)
  224. return
  225. }
  226. if b == nil {
  227. res = nil
  228. return
  229. }
  230. if err = json.Unmarshal(b, &res); err != nil {
  231. log.Error("s.Ltime.Unmarshal((%v), err(%v)", b, err)
  232. return
  233. }
  234. if res["time"] != nil {
  235. if st, ok := res["time"].(float64); ok {
  236. res["currentTime"] = time.Now().Unix() - int64(st)
  237. }
  238. }
  239. return
  240. }
  241. // LikeAct service
  242. func (s *Service) LikeAct(c context.Context, p *l.ParamAddLikeAct, mid int64) (res int64, err error) {
  243. var (
  244. subject *l.SubjectItem
  245. likeItem *l.Item
  246. memberRly *accapi.ProfileReply
  247. subErr error
  248. likeErr error
  249. )
  250. eg, errCtx := errgroup.WithContext(c)
  251. eg.Go(func() error {
  252. subject, subErr = s.dao.ActSubject(errCtx, p.Sid)
  253. return subErr
  254. })
  255. eg.Go(func() error {
  256. likeItem, likeErr = s.dao.Like(errCtx, p.Lid)
  257. return likeErr
  258. })
  259. if err = eg.Wait(); err != nil {
  260. log.Error("eg.Wait error(%v)", err)
  261. return
  262. }
  263. if subject.ID == 0 || subject.Type == l.STORYKING {
  264. err = ecode.ActivityHasOffLine
  265. return
  266. }
  267. if likeItem.ID == 0 || likeItem.Sid != p.Sid {
  268. err = ecode.ActivityLikeHasOffLine
  269. return
  270. }
  271. if memberRly, err = s.accClient.Profile3(c, &accapi.MidReq{Mid: mid}); err != nil {
  272. log.Error(" s.acc.Profile3(c,&accmdl.ArgMid{Mid:%d}) error(%v)", mid, err)
  273. return
  274. }
  275. if err = s.judgeUser(c, subject, memberRly.Profile); err != nil {
  276. return
  277. }
  278. nowTime := time.Now().Unix()
  279. if int64(memberRly.Profile.JoinTime) >= (nowTime - 86400*7) {
  280. err = ecode.ActivityLikeMemberLimit
  281. return
  282. }
  283. if int64(subject.Lstime) >= nowTime {
  284. err = ecode.ActivityLikeNotStart
  285. return
  286. }
  287. if int64(subject.Letime) <= nowTime {
  288. err = ecode.ActivityLikeHasEnd
  289. return
  290. }
  291. var (
  292. likeAct map[int64]int
  293. lids = []int64{p.Lid}
  294. )
  295. if likeAct, err = s.dao.LikeActs(c, p.Sid, mid, lids); err != nil {
  296. log.Error("s.dao.LikeActMidList(%v) error(%+v)", p, err)
  297. return
  298. }
  299. if _, ok := likeAct[p.Lid]; !ok {
  300. log.Error("s.dao.LikeActMidList() get lid value error()")
  301. return
  302. }
  303. isLikeType := s.isLikeType(c, subject.Type)
  304. if likeAct[p.Lid] == like.HasLike {
  305. if isLikeType == _like {
  306. err = ecode.ActivityLikeHasLike
  307. } else if isLikeType == _vote {
  308. err = ecode.ActivityLikeHasVote
  309. } else {
  310. err = ecode.ActivityLikeHasGrade
  311. }
  312. return
  313. }
  314. var score int64
  315. if isLikeType == _like || isLikeType == _vote {
  316. score = l.LIKESCORE
  317. } else {
  318. score = p.Score
  319. }
  320. if err = s.dao.SetRedisCache(c, p.Sid, p.Lid, score, likeItem.Type); err != nil {
  321. log.Error("s.dao.SetRedisCache(%v) error(%+v)", p, err)
  322. return
  323. }
  324. likeActAdd := &l.Action{
  325. Lid: p.Lid,
  326. Mid: mid,
  327. Sid: p.Sid,
  328. Action: score,
  329. IPv6: make([]byte, 0),
  330. }
  331. if IPv6 := net.ParseIP(metadata.String(c, metadata.RemoteIP)); IPv6 != nil {
  332. likeActAdd.IPv6 = IPv6
  333. }
  334. if res, err = s.dao.LikeActAdd(c, likeActAdd); err != nil {
  335. log.Error("s.dao.LikeActAdd(%v) error(%+v)", p, err)
  336. return
  337. }
  338. s.dao.AddCacheLikeActs(c, p.Sid, mid, map[int64]int{p.Lid: like.HasLike})
  339. return
  340. }
  341. // StoryKingAct .
  342. func (s *Service) StoryKingAct(c context.Context, p *l.ParamStoryKingAct, mid int64) (res map[string]int64, err error) {
  343. var (
  344. subject *l.SubjectItem
  345. likeItem *l.Item
  346. memberRly *accapi.ProfileReply
  347. subErr error
  348. likeErr error
  349. leftTime int64
  350. )
  351. eg, errCtx := errgroup.WithContext(c)
  352. eg.Go(func() error {
  353. subject, subErr = s.dao.ActSubject(errCtx, p.Sid)
  354. return subErr
  355. })
  356. eg.Go(func() error {
  357. likeItem, likeErr = s.dao.Like(errCtx, p.Lid)
  358. return likeErr
  359. })
  360. if err = eg.Wait(); err != nil {
  361. log.Error("eg.Wait error(%v)", err)
  362. return
  363. }
  364. if subject.ID == 0 || subject.Type != l.STORYKING {
  365. err = ecode.ActivityHasOffLine
  366. return
  367. }
  368. if likeItem.ID == 0 || likeItem.Sid != p.Sid {
  369. err = ecode.ActivityLikeHasOffLine
  370. return
  371. }
  372. if memberRly, err = s.accClient.Profile3(c, &accapi.MidReq{Mid: mid}); err != nil {
  373. log.Error(" s.acc.Profile3(c,&accmdl.ArgMid{Mid:%d}) error(%v)", mid, err)
  374. return
  375. }
  376. if err = s.judgeUser(c, subject, memberRly.Profile); err != nil {
  377. return
  378. }
  379. nowTime := time.Now().Unix()
  380. if int64(subject.Lstime) >= nowTime {
  381. err = ecode.ActivityLikeNotStart
  382. return
  383. }
  384. if int64(subject.Letime) <= nowTime {
  385. err = ecode.ActivityLikeHasEnd
  386. return
  387. }
  388. if leftTime, err = s.storyLikeCheck(c, p.Sid, p.Lid, mid, subject.DailyLikeLimit, subject.DailySingleLikeLimit); err != nil {
  389. log.Error(" s.storyLikeCheck(%d,%d,%d) error(%+v)", p.Sid, p.Lid, mid, err)
  390. return
  391. }
  392. if leftTime < p.Score {
  393. if leftTime > 0 {
  394. p.Score = leftTime
  395. } else {
  396. err = ecode.ActivityOverDailyScore
  397. return
  398. }
  399. }
  400. if err = s.dao.SetRedisCache(c, p.Sid, p.Lid, p.Score, likeItem.Type); err != nil {
  401. log.Error("s.dao.SetRedisCache(%v) error(%+v)", p, err)
  402. return
  403. }
  404. likeActAdd := &l.Action{
  405. Lid: p.Lid,
  406. Mid: mid,
  407. Sid: p.Sid,
  408. Action: int64(p.Score),
  409. IPv6: make([]byte, 0),
  410. }
  411. if IPv6 := net.ParseIP(metadata.String(c, metadata.RemoteIP)); IPv6 != nil {
  412. likeActAdd.IPv6 = IPv6
  413. }
  414. res = make(map[string]int64, 2)
  415. if res["act_id"], err = s.dao.LikeActAdd(c, likeActAdd); err != nil {
  416. log.Error("s.dao.LikeActAdd(%v) error(%+v)", p, err)
  417. return
  418. }
  419. s.storyLikeActSet(c, p.Sid, p.Lid, mid, p.Score)
  420. res["score"] = p.Score
  421. return
  422. }
  423. // StoryKingLeftTime .
  424. func (s *Service) StoryKingLeftTime(c context.Context, sid, mid int64) (res int64, err error) {
  425. var (
  426. subject *l.SubjectItem
  427. memberRly *accapi.ProfileReply
  428. )
  429. if subject, err = s.dao.ActSubject(c, sid); err != nil {
  430. return
  431. }
  432. if subject.ID == 0 || subject.Type != l.STORYKING {
  433. err = ecode.ActivityHasOffLine
  434. return
  435. }
  436. if memberRly, err = s.accClient.Profile3(c, &accapi.MidReq{Mid: mid}); err != nil {
  437. log.Error(" s.acc.Profile3(c,&accmdl.ArgMid{Mid:%d}) error(%v)", mid, err)
  438. return
  439. }
  440. if err = s.simpleJudge(c, subject, memberRly.Profile); err != nil {
  441. err = nil
  442. res = 0
  443. return
  444. }
  445. nowTime := time.Now().Unix()
  446. if int64(subject.Lstime) >= nowTime || int64(subject.Letime) <= nowTime {
  447. res = 0
  448. return
  449. }
  450. if res, err = s.storySumUsed(c, sid, mid); err != nil {
  451. log.Error("s.storySumUsed(%d,%d) error(%+v)", sid, mid, err)
  452. return
  453. }
  454. res = subject.DailyLikeLimit - res
  455. if res < 0 {
  456. res = 0
  457. }
  458. return
  459. }
  460. // UpList .
  461. func (s *Service) UpList(c context.Context, p *l.ParamList, mid int64) (res *l.ListInfo, err error) {
  462. switch p.Type {
  463. case like.EsOrderLikes, like.EsOrderCoin, like.EsOrderReply, like.EsOrderShare, like.EsOrderClick, like.EsOrderDm, like.EsOrderFav:
  464. res, err = s.EsList(c, p, mid)
  465. case like.ActOrderCtime, like.ActOrderLike, like.ActOrderRandom:
  466. res, err = s.StoryKingList(c, p, mid)
  467. default:
  468. err = errors.New("type error")
  469. }
  470. return
  471. }
  472. // EsList .
  473. func (s *Service) EsList(c context.Context, p *l.ParamList, mid int64) (res *l.ListInfo, err error) {
  474. var (
  475. subject *l.SubjectItem
  476. )
  477. if subject, err = s.dao.ActSubject(c, p.Sid); err != nil {
  478. return
  479. }
  480. if subject.ID == 0 {
  481. err = ecode.ActivityHasOffLine
  482. return
  483. }
  484. if res, err = s.dao.ListFromES(c, p.Sid, p.Type, p.Ps, p.Pn, 0); err != nil {
  485. log.Error("s.dao.ListFromES(%d) error(%+v)", p.Sid, err)
  486. return
  487. }
  488. if res == nil || len(res.List) == 0 {
  489. return
  490. }
  491. if err = s.getContent(c, res.List, subject.Type, mid, p.Type); err != nil {
  492. log.Error("s.getContent(%d) error(%v)", p.Sid, err)
  493. }
  494. return
  495. }
  496. // StoryKingList .
  497. func (s *Service) StoryKingList(c context.Context, p *l.ParamList, mid int64) (res *l.ListInfo, err error) {
  498. var (
  499. subject *l.SubjectItem
  500. likeList []*l.List
  501. total int64
  502. )
  503. if subject, err = s.dao.ActSubject(c, p.Sid); err != nil {
  504. return
  505. }
  506. if subject.ID == 0 {
  507. err = ecode.ActivityHasOffLine
  508. return
  509. }
  510. likesType := checkIsLike(subject.Type)
  511. switch p.Type {
  512. case like.ActOrderCtime:
  513. likeList, err = s.orderByCtime(c, p.Sid, p.Pn, p.Ps, likesType)
  514. case like.ActOrderRandom:
  515. likeList, err = s.orderByRandom(c, p.Sid, p.Pn, p.Ps, likesType)
  516. default:
  517. likeList, err = s.orderByLike(c, p.Sid, p.Pn, p.Ps)
  518. }
  519. if err != nil {
  520. log.Error("s.orderBy(%s)(%d) error(%v)", p.Type, p.Sid, err)
  521. return
  522. }
  523. if len(likeList) == 0 {
  524. return
  525. }
  526. if err = s.getContent(c, likeList, subject.Type, mid, p.Type); err != nil {
  527. log.Error("s.getContent(%d) error(%v)", p.Sid, err)
  528. }
  529. if p.Type == like.ActOrderRandom {
  530. total, _ = s.dao.LikeRandomCount(c, p.Sid)
  531. } else {
  532. total, _ = s.dao.LikeCount(c, p.Sid)
  533. }
  534. res = &l.ListInfo{List: likeList, Page: &l.Page{Size: p.Ps, Num: p.Pn, Total: total}}
  535. return
  536. }
  537. // getContent get likes extends 后期接入其他活动补充完善.
  538. func (s *Service) getContent(c context.Context, list []*l.List, subType, mid int64, order string) (err error) {
  539. switch subType {
  540. case l.STORYKING:
  541. err = s.actContent(c, list, mid)
  542. case l.PICTURE, l.PICTURELIKE, l.DRAWYOO, l.DRAWYOOLIKE, l.TEXT, l.TEXTLIKE, l.QUESTION:
  543. err = s.contentAccount(c, list)
  544. case l.VIDEOLIKE, l.VIDEO, l.VIDEO2, l.SMALLVIDEO, l.PHONEVIDEO, l.ONLINEVOTE:
  545. err = s.arcTag(c, list, order, mid)
  546. default:
  547. err = ecode.RequestErr
  548. }
  549. return
  550. }
  551. // actContent get like_content and account info.
  552. func (s *Service) contentAccount(c context.Context, list []*l.List) (err error) {
  553. var (
  554. lt = len(list)
  555. lids = make([]int64, 0, lt)
  556. mids = make([]int64, 0, lt)
  557. cont map[int64]*l.LikeContent
  558. actRly *accapi.InfosReply
  559. )
  560. for _, v := range list {
  561. lids = append(lids, v.ID)
  562. if v.Mid > 0 {
  563. mids = append(mids, v.Mid)
  564. }
  565. }
  566. eg, errCtx := errgroup.WithContext(c)
  567. eg.Go(func() (e error) {
  568. cont, e = s.dao.LikeContent(errCtx, lids)
  569. return
  570. })
  571. eg.Go(func() (e error) {
  572. actRly, e = s.accClient.Infos3(errCtx, &accapi.MidsReq{Mids: mids})
  573. return
  574. })
  575. if err = eg.Wait(); err != nil {
  576. log.Error("actContent:eg.Wait() error(%v)", err)
  577. return
  578. }
  579. for _, v := range list {
  580. obj := make(map[string]interface{}, 2)
  581. if _, ok := cont[v.ID]; ok {
  582. obj["cont"] = cont[v.ID]
  583. }
  584. if _, k := actRly.Infos[v.Mid]; k {
  585. obj["act"] = actRly.Infos[v.Mid]
  586. }
  587. v.Object = obj
  588. }
  589. return
  590. }
  591. // actContent get like_content and account info.
  592. func (s *Service) actContent(c context.Context, list []*l.List, mid int64) (err error) {
  593. var (
  594. lt = len(list)
  595. lids = make([]int64, 0, lt)
  596. wids = make([]int64, 0, lt)
  597. cont map[int64]*l.LikeContent
  598. accRly *accapi.InfosReply
  599. ip = metadata.String(c, metadata.RemoteIP)
  600. followersRly *accapi.RelationsReply
  601. )
  602. for _, v := range list {
  603. lids = append(lids, v.ID)
  604. if v.Wid > 0 {
  605. wids = append(wids, v.Wid)
  606. }
  607. }
  608. eg, errCtx := errgroup.WithContext(c)
  609. eg.Go(func() (e error) {
  610. cont, e = s.dao.LikeContent(errCtx, lids)
  611. return
  612. })
  613. eg.Go(func() (e error) {
  614. accRly, e = s.accClient.Infos3(errCtx, &accapi.MidsReq{Mids: wids})
  615. return
  616. })
  617. if mid > 0 {
  618. eg.Go(func() (e error) {
  619. followersRly, e = s.accClient.Relations3(errCtx, &accapi.RelationsReq{Mid: mid, Owners: wids, RealIp: ip})
  620. return
  621. })
  622. }
  623. if err = eg.Wait(); err != nil {
  624. log.Error("actContent:eg.Wait() error(%v)", err)
  625. return
  626. }
  627. for _, v := range list {
  628. obj := make(map[string]interface{}, 2)
  629. if _, ok := cont[v.ID]; ok {
  630. obj["cont"] = cont[v.ID]
  631. }
  632. var t struct {
  633. *accapi.Info
  634. Following bool `json:"following"`
  635. }
  636. if _, k := accRly.Infos[v.Wid]; k {
  637. t.Info = accRly.Infos[v.Wid]
  638. }
  639. if mid > 0 {
  640. if _, f := followersRly.Relations[v.Wid]; f {
  641. t.Following = followersRly.Relations[v.Wid].Following
  642. }
  643. }
  644. obj["act"] = t
  645. v.Object = obj
  646. }
  647. return
  648. }
  649. // orderByCtime .
  650. func (s *Service) orderByCtime(c context.Context, sid int64, pn, ps int, likesType bool) (res []*l.List, err error) {
  651. var (
  652. lids []int64
  653. start = (pn - 1) * ps
  654. end = start + ps - 1
  655. items map[int64]*l.Item
  656. likeAct map[int64]int64
  657. )
  658. if lids, err = s.dao.LikeCtime(c, sid, start, end); err != nil {
  659. log.Error("s.dao.LikeCtime(%d,%d,%d) error(%+v)", sid, start, end, err)
  660. return
  661. }
  662. lt := len(lids)
  663. if lt == 0 {
  664. return
  665. }
  666. eg, errCtx := errgroup.WithContext(c)
  667. eg.Go(func() (e error) {
  668. items, e = s.dao.Likes(errCtx, lids)
  669. return
  670. })
  671. if likesType {
  672. eg.Go(func() (e error) {
  673. likeAct, e = s.dao.LikeActLidCounts(c, lids)
  674. return
  675. })
  676. }
  677. if err = eg.Wait(); err != nil {
  678. log.Error("orderByCtime:eg.Wait() error(%+v)", err)
  679. return
  680. }
  681. res = make([]*l.List, 0, lt)
  682. for _, v := range lids {
  683. if _, ok := items[v]; ok && items[v].ID > 0 {
  684. t := &l.List{Item: items[v]}
  685. if likesType {
  686. if _, f := likeAct[v]; f {
  687. t.Like = likeAct[v]
  688. }
  689. }
  690. res = append(res, t)
  691. } else {
  692. log.Info("s.dao.CacheLikes(%d) not found", v)
  693. }
  694. }
  695. return
  696. }
  697. // orderByRandom order by random
  698. func (s *Service) orderByRandom(c context.Context, sid int64, pn, ps int, likesType bool) (res []*l.List, err error) {
  699. var (
  700. lids []int64
  701. start = (pn - 1) * ps
  702. end = start + ps - 1
  703. items map[int64]*l.Item
  704. likeAct map[int64]int64
  705. orderIDs []int64
  706. orderList *l.ListInfo
  707. )
  708. if lids, err = s.dao.LikeRandom(c, sid, start, end); err != nil {
  709. log.Error("s.dao.LikeRandom(%d,%d,%d) error(%+v)", sid, start, end, err)
  710. return
  711. }
  712. lt := len(lids)
  713. if lt == 0 {
  714. if orderList, err = s.dao.ListFromES(c, sid, "", 500, 1, time.Now().Unix()); err != nil {
  715. log.Error("s.dao.ListFromES(%d) error(%+v)", sid, err)
  716. return
  717. }
  718. if orderList == nil || len(orderList.List) == 0 {
  719. return
  720. }
  721. orderLen := len(orderList.List)
  722. orderIDs = make([]int64, 0, orderLen)
  723. for _, v := range orderList.List {
  724. orderIDs = append(orderIDs, v.ID)
  725. }
  726. if err = s.dao.SetLikeRandom(c, sid, orderIDs); err != nil {
  727. log.Error("s.dao.SetLikeRandom(%d) error(%+v)", sid, err)
  728. return
  729. }
  730. if lids, err = s.dao.LikeRandom(c, sid, start, end); err != nil {
  731. log.Error("s.dao.LikeRandom(%d,%d,%d) error(%+v)", sid, start, end, err)
  732. return
  733. }
  734. }
  735. if len(lids) == 0 {
  736. return
  737. }
  738. eg, errCtx := errgroup.WithContext(c)
  739. eg.Go(func() (e error) {
  740. items, e = s.dao.Likes(errCtx, lids)
  741. return
  742. })
  743. if likesType {
  744. eg.Go(func() (e error) {
  745. likeAct, _ = s.dao.LikeActLidCounts(c, lids)
  746. return
  747. })
  748. }
  749. if err = eg.Wait(); err != nil {
  750. log.Error("orderByRandom:eg.Wait() error(%+v)", err)
  751. return
  752. }
  753. res = make([]*l.List, 0, lt)
  754. for _, v := range lids {
  755. if _, ok := items[v]; ok && items[v].ID > 0 {
  756. t := &l.List{Item: items[v]}
  757. if likesType {
  758. if _, f := likeAct[v]; f {
  759. t.Like = likeAct[v]
  760. }
  761. }
  762. res = append(res, t)
  763. } else {
  764. log.Info("s.dao.orderByRandom(%d) not found", v)
  765. }
  766. }
  767. return
  768. }
  769. // orderByLike only fo like .
  770. func (s *Service) orderByLike(c context.Context, sid int64, pn, ps int) (res []*l.List, err error) {
  771. var (
  772. lids []int64
  773. lt int
  774. items map[int64]*l.Item
  775. start = (pn - 1) * ps
  776. end = start + ps - 1
  777. )
  778. infos, err := s.dao.RedisCache(c, sid, start, end)
  779. if err != nil {
  780. log.Error("s.dao.RedisCache(%d,%d,%d) error(%+v)", sid, start, end, err)
  781. return
  782. }
  783. lt = len(infos)
  784. if lt == 0 {
  785. return
  786. }
  787. lids = make([]int64, 0, lt)
  788. for _, v := range infos {
  789. lids = append(lids, v.Lid)
  790. }
  791. if items, err = s.dao.Likes(c, lids); err != nil {
  792. log.Error("s.dao.CacheLikes(%v) error(%+v)", lids, err)
  793. return
  794. }
  795. res = make([]*l.List, 0, lt)
  796. for _, v := range infos {
  797. if _, ok := items[v.Lid]; ok && items[v.Lid].ID > 0 {
  798. t := &l.List{Item: items[v.Lid], Like: v.Score}
  799. res = append(res, t)
  800. } else {
  801. log.Info("s.dao.CacheLikes(%d) not found", v.Lid)
  802. }
  803. }
  804. return
  805. }
  806. // storyLikeCheck .
  807. func (s *Service) storyLikeCheck(c context.Context, sid, lid, mid, storyMaxAct, storyEachMaxAct int64) (left int64, err error) {
  808. var (
  809. sumScore, lScore int64
  810. maxLeft, lLeft int64
  811. )
  812. eg, errCtx := errgroup.WithContext(c)
  813. eg.Go(func() (e error) {
  814. sumScore, e = s.storySumUsed(errCtx, sid, mid)
  815. return
  816. })
  817. eg.Go(func() (e error) {
  818. lScore, e = s.storyEachUsed(errCtx, sid, mid, lid)
  819. return
  820. })
  821. if err = eg.Wait(); err != nil {
  822. err = errors.Wrap(err, "eg.Wait()")
  823. return
  824. }
  825. maxLeft = storyMaxAct - sumScore
  826. lLeft = storyEachMaxAct - lScore
  827. left = int64(math.Min(float64(maxLeft), float64(lLeft)))
  828. if left <= 0 {
  829. left = 0
  830. }
  831. return
  832. }
  833. // storyLikeActSet .
  834. func (s *Service) storyLikeActSet(c context.Context, sid, lid, mid int64, score int64) (err error) {
  835. eg, errCtx := errgroup.WithContext(c)
  836. eg.Go(func() (e error) {
  837. _, e = s.dao.IncrStoryLikeSum(errCtx, sid, mid, score)
  838. return
  839. })
  840. eg.Go(func() (e error) {
  841. _, e = s.dao.IncrStoryEachLikeAct(errCtx, sid, mid, lid, score)
  842. return
  843. })
  844. if err = eg.Wait(); err != nil {
  845. log.Error("storyLikeActSet:eg.Wait() error(%+v)", err)
  846. }
  847. return
  848. }
  849. // storySumUsed .
  850. func (s *Service) storySumUsed(c context.Context, sid, mid int64) (res int64, err error) {
  851. if res, err = s.dao.StoryLikeSum(c, sid, mid); err != nil {
  852. log.Error("s.dao.StoryLikeSum(%d,%d) error(%+v)", sid, mid, err)
  853. return
  854. }
  855. if res == -1 {
  856. today := time.Now().Format("2006-01-02")
  857. etime := fmt.Sprintf("%s 23:59:59", today)
  858. stime := fmt.Sprintf("%s 00:00:00", today)
  859. if res, err = s.dao.StoryLikeActSum(c, sid, mid, stime, etime); err != nil {
  860. log.Error("s.dao.StoryLikeActSum(%d,%d) error(%+v)", sid, mid, err)
  861. return
  862. }
  863. if err = s.dao.SetLikeSum(c, sid, mid, res); err != nil {
  864. log.Error("s.dao.SetLikeSum(%d,%d,%d) error(%+v)", sid, mid, res, err)
  865. }
  866. }
  867. return
  868. }
  869. func (s *Service) storyEachUsed(c context.Context, sid, mid, lid int64) (res int64, err error) {
  870. if res, err = s.dao.StoryEachLikeSum(c, sid, mid, lid); err != nil {
  871. log.Error("s.dao.StoryEachLikeSum(%d,%d) error(%+v)", sid, mid, err)
  872. return
  873. }
  874. if res == -1 {
  875. today := time.Now().Format("2006-01-02")
  876. etime := fmt.Sprintf("%s 23:59:59", today)
  877. stime := fmt.Sprintf("%s 00:00:00", today)
  878. if res, err = s.dao.StoryEachLikeAct(c, sid, mid, lid, stime, etime); err != nil {
  879. log.Error("s.dao.StoryLikeActSum(%d,%d) error(%+v)", sid, mid, err)
  880. return
  881. }
  882. if err = s.dao.SetEachLikeSum(c, sid, mid, lid, res); err != nil {
  883. log.Error("s.dao.SetEachLikeSum(%d,%d,%d) error(%+v)", sid, mid, res, err)
  884. }
  885. }
  886. return
  887. }
  888. // LikeActList get sid&lid likeact list .
  889. func (s *Service) LikeActList(c context.Context, sid, mid int64, lids []int64) (res map[int64]interface{}, err error) {
  890. var (
  891. likeCounts map[int64]int64
  892. likeActs map[int64]int
  893. likeCount int64
  894. isLike int
  895. )
  896. group, ctx := errgroup.WithContext(c)
  897. group.Go(func() (e error) {
  898. if likeCounts, e = s.dao.LikeActLidCounts(ctx, lids); e != nil {
  899. log.Error("s.dao.LikeActLidCounts(%v) error(%+v)", lids, e)
  900. return e
  901. }
  902. return nil
  903. })
  904. if mid > 0 {
  905. group.Go(func() (e error) {
  906. if likeActs, e = s.dao.LikeActs(ctx, sid, mid, lids); e != nil {
  907. log.Error("s.dao.LikeActMidList(%v,%d,%d) error(%+v)", lids, sid, mid, e)
  908. return e
  909. }
  910. return nil
  911. })
  912. }
  913. if err = group.Wait(); err != nil {
  914. log.Error("get likeactListerror(%v)", err)
  915. return
  916. }
  917. res = make(map[int64]interface{}, len(lids))
  918. for _, lid := range lids {
  919. if _, ok := likeCounts[lid]; ok {
  920. likeCount = likeCounts[lid]
  921. } else {
  922. likeCount = 0
  923. }
  924. if _, ok := likeActs[lid]; ok {
  925. isLike = likeActs[lid]
  926. } else {
  927. isLike = 0
  928. }
  929. res[lid] = map[string]interface{}{
  930. "likeCount": likeCount,
  931. "isLike": isLike,
  932. }
  933. }
  934. return
  935. }
  936. // isLikeType range liketype find out real type .
  937. func (s *Service) isLikeType(c context.Context, subType int64) (res string) {
  938. for _, ty := range l.LIKETYPE {
  939. if subType == ty {
  940. res = _like
  941. return
  942. }
  943. }
  944. if subType == l.MUSIC {
  945. res = _vote
  946. } else {
  947. res = _grade
  948. }
  949. return
  950. }
  951. // simpleJudge judge user could like or not .
  952. func (s *Service) simpleJudge(c context.Context, subject *l.SubjectItem, member *accapi.Profile) (err error) {
  953. if member.Silence == _silenceForbid {
  954. err = ecode.ActivityMemberBlocked
  955. return
  956. }
  957. if subject.Flag == 0 {
  958. return
  959. }
  960. if (subject.Flag & l.FLAGSPY) == l.FLAGSPY {
  961. var userScore *spymdl.UserScore
  962. if userScore, err = s.spy.UserScore(c, &spymdl.ArgUserScore{Mid: member.Mid}); err != nil {
  963. log.Error("s.spy.UserScore(%d) error(%v)", member.Mid, err)
  964. return
  965. }
  966. if int64(userScore.Score) <= s.c.Rule.Spylike {
  967. err = ecode.ActivityLikeScoreLower
  968. return
  969. }
  970. }
  971. if (subject.Flag & l.FLAGUSTIME) == l.FLAGUSTIME {
  972. if subject.Ustime <= xtime.Time(member.JoinTime) {
  973. err = ecode.ActivityLikeRegisterLimit
  974. return
  975. }
  976. }
  977. if (subject.Flag & l.FLAGUETIME) == l.FLAGUETIME {
  978. if subject.Uetime >= xtime.Time(member.JoinTime) {
  979. err = ecode.ActivityLikeBeforeRegister
  980. return
  981. }
  982. }
  983. if (subject.Flag & l.FLAGPHONEBIND) == l.FLAGPHONEBIND {
  984. if member.TelStatus != 1 {
  985. err = ecode.ActivityTelValid
  986. return
  987. }
  988. }
  989. if (subject.Flag & l.FLAGLEVEL) == l.FLAGLEVEL {
  990. if subject.Level > int64(member.Level) {
  991. err = ecode.ActivityLikeLevelLimit
  992. }
  993. }
  994. return
  995. }
  996. // judgeUser judge user could like or not .
  997. func (s *Service) judgeUser(c context.Context, subject *l.SubjectItem, member *accapi.Profile) (err error) {
  998. if member.Silence == _silenceForbid {
  999. err = ecode.ActivityMemberBlocked
  1000. return
  1001. }
  1002. if subject.Flag == 0 {
  1003. return
  1004. }
  1005. if (subject.Flag & l.FLAGIP) == l.FLAGIP {
  1006. ip := metadata.String(c, metadata.RemoteIP)
  1007. var used int
  1008. if used, err = s.dao.IPReqquestCheck(c, ip); err != nil {
  1009. log.Error("s.dao.IpReqquestCheck(%s) error(%+v)", ip, err)
  1010. return
  1011. }
  1012. if used == 0 {
  1013. if err = s.dao.SetIPRequest(c, ip); err != nil {
  1014. log.Error("s.dao.SetIPRequest(%s) error(%+v)", ip, err)
  1015. return
  1016. }
  1017. } else {
  1018. err = ecode.ActivityLikeIPFrequence
  1019. return
  1020. }
  1021. }
  1022. if (subject.Flag & l.FLAGSPY) == l.FLAGSPY {
  1023. var userScore *spymdl.UserScore
  1024. if userScore, err = s.spy.UserScore(c, &spymdl.ArgUserScore{Mid: member.Mid}); err != nil {
  1025. log.Error("s.spy.UserScore(%d) error(%v)", member.Mid, err)
  1026. return
  1027. }
  1028. if int64(userScore.Score) <= s.c.Rule.Spylike {
  1029. err = ecode.ActivityLikeScoreLower
  1030. return
  1031. }
  1032. }
  1033. if (subject.Flag & l.FLAGUSTIME) == l.FLAGUSTIME {
  1034. if subject.Ustime <= xtime.Time(member.JoinTime) {
  1035. err = ecode.ActivityLikeRegisterLimit
  1036. return
  1037. }
  1038. }
  1039. if (subject.Flag & l.FLAGUETIME) == l.FLAGUETIME {
  1040. if subject.Uetime >= xtime.Time(member.JoinTime) {
  1041. err = ecode.ActivityLikeBeforeRegister
  1042. return
  1043. }
  1044. }
  1045. if (subject.Flag & l.FLAGPHONEBIND) == l.FLAGPHONEBIND {
  1046. if member.TelStatus != 1 {
  1047. err = ecode.ActivityTelValid
  1048. return
  1049. }
  1050. }
  1051. if (subject.Flag & l.FLAGLEVEL) == l.FLAGLEVEL {
  1052. if subject.Level > int64(member.Level) {
  1053. err = ecode.ActivityLikeLevelLimit
  1054. }
  1055. }
  1056. return
  1057. }
  1058. // Close service
  1059. func (s *Service) Close() {
  1060. s.dao.Close()
  1061. }
  1062. // Ping service
  1063. func (s *Service) Ping(c context.Context) (err error) {
  1064. err = s.dao.Ping(c)
  1065. return
  1066. }
  1067. func (s *Service) arcTypeproc() {
  1068. for {
  1069. if types, err := s.arcRPC.Types2(context.Background()); err != nil {
  1070. log.Error("s.arcRPC.Types2 error(%v)", err)
  1071. time.Sleep(time.Second)
  1072. } else {
  1073. s.arcType = types
  1074. }
  1075. time.Sleep(time.Duration(s.c.Interval.PullArcTypeInterval))
  1076. }
  1077. }
  1078. func (s *Service) initDialect() {
  1079. tmpTag := make(map[int64]struct{}, len(s.c.Rule.DialectTags))
  1080. for _, v := range s.c.Rule.DialectTags {
  1081. tmpTag[v] = struct{}{}
  1082. }
  1083. tmpRegion := make(map[int16]struct{}, len(s.c.Rule.DialectRegions))
  1084. for _, v := range s.c.Rule.DialectRegions {
  1085. tmpRegion[v] = struct{}{}
  1086. }
  1087. s.dialectTags = tmpTag
  1088. s.dialectRegions = tmpRegion
  1089. }
  1090. func (s *Service) actSourceproc() {
  1091. for {
  1092. if s.c.Rule.DialectSid != 0 {
  1093. s.updateActSourceList(context.Background(), s.c.Rule.DialectSid, _typeAll)
  1094. }
  1095. if len(s.c.Rule.SpecialSids) > 0 {
  1096. for _, sid := range s.c.Rule.SpecialSids {
  1097. if sid > 0 {
  1098. s.updateActSourceList(context.Background(), sid, _typeRegion)
  1099. }
  1100. }
  1101. }
  1102. time.Sleep(time.Duration(s.c.Interval.ActSourceInterval))
  1103. }
  1104. }
  1105. func (s *Service) initReward() {
  1106. tmp := make(map[int]*bnjmdl.Reward, len(s.c.Bnj2019.Reward))
  1107. for _, v := range s.c.Bnj2019.Reward {
  1108. tmp[v.Step] = v
  1109. }
  1110. s.reward = tmp
  1111. }