jy.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. package jy
  2. import (
  3. "app.yhyue.com/moapp/jybase/sms"
  4. "encoding/json"
  5. "fmt"
  6. "log"
  7. "net/http"
  8. "regexp"
  9. "sort"
  10. "strings"
  11. "time"
  12. util "app.yhyue.com/moapp/jybase/common"
  13. . "app.yhyue.com/moapp/jybase/date"
  14. "app.yhyue.com/moapp/jybase/es"
  15. "app.yhyue.com/moapp/jybase/go-xweb/httpsession"
  16. "app.yhyue.com/moapp/jybase/mail"
  17. . "app.yhyue.com/moapp/jybase/mongodb"
  18. "app.yhyue.com/moapp/jybase/redis"
  19. qrpc "app.yhyue.com/moapp/jybase/rpc"
  20. . "app.yhyue.com/moapp/jypkg/middleground"
  21. "bp.jydev.jianyu360.cn/BaseService/userCenter/rpc/pb"
  22. )
  23. // 获取用户合并以前,合并以后的openid
  24. func GetOldOpenid(s_m_openid, a_m_openid, s_phone string, mergeorder interface{}) string {
  25. a_mergeorder, _ := mergeorder.([]interface{})
  26. openid := ""
  27. if len(a_mergeorder) > 0 {
  28. first, _ := a_mergeorder[0].(string)
  29. if first == "s_m_openid" {
  30. openid = s_m_openid
  31. } else if first == "a_m_openid" {
  32. openid = a_m_openid
  33. } else if first == "s_phone" {
  34. openid = s_phone
  35. }
  36. } else {
  37. if s_m_openid != "" {
  38. openid = s_m_openid
  39. } else if a_m_openid != "" {
  40. openid = a_m_openid
  41. } else if s_phone != "" {
  42. openid = s_phone
  43. }
  44. }
  45. return openid
  46. }
  47. var ClearHtml = regexp.MustCompile("<[^>]*>")
  48. var MatchSpace = regexp.MustCompile("\\s+")
  49. var filterReg_3 = regexp.MustCompile("(项目|公告|公示)$")
  50. var filterReg_2 = regexp.MustCompile("^[)\\)>》】\\]}}〕,,;;::'\"“”。.\\??、/+=\\_—*&……\\^%$¥@!!`~·(\\(<《【\\[{{〔]+$")
  51. var filterReg_1 = regexp.MustCompile("^([0-9]{1,3}|[零一二三四五六七八九十]{1,2}|联系人?|电话|地址|编号|采购|政府采购|成交|更正|招标|中标|变更|结果)$")
  52. var filterReg = regexp.MustCompile("^[的人号时元万公告项目地址电话邮编日期联系招标中结果成交项目项目采购采购项目政府采购公告更正公告]+$")
  53. var PhoneReg = regexp.MustCompile("^[1][3-9][0-9]{9}$")
  54. var EmailPattern = regexp.MustCompile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$")
  55. var filterReg_4 = regexp.MustCompile("([)>》】\\]\\}}〕。,,;;::'\"“”。\\.\\??、/\\+=\\\\_—\\*&……\\^%$¥@!!`~·(\\(<《【\\[\\{{〔])")
  56. // P279删除通用过滤词,例如“公告”
  57. func FilteKey(k string) string {
  58. k = strings.TrimSpace(k)
  59. // k = filterReg_3.ReplaceAllString(k, "")
  60. k = filterReg_4.ReplaceAllString(k, " ")
  61. // k = filterReg_1.ReplaceAllString(k, "")
  62. // k = filterReg.ReplaceAllString(k, "")
  63. return k
  64. }
  65. // InterceptSearchKW 超过20个字,截断
  66. // 返回截取后的字符串和截取掉中的前3个字
  67. func InterceptSearchKW(word string, keywordsLimit int, isFilter bool) (b_word, a_word, s_word string) {
  68. if word == "" {
  69. return
  70. }
  71. if isFilter {
  72. word = FilteKey(word)
  73. }
  74. word = MatchSpace.ReplaceAllString(strings.TrimSpace(word), " ")
  75. words := []rune(word)
  76. if len(words) > keywordsLimit {
  77. b_word = string(words[:keywordsLimit])
  78. b_word = strings.TrimSpace(b_word)
  79. if len(words) > keywordsLimit+3 {
  80. a_word = string(words[keywordsLimit : keywordsLimit+3])
  81. } else {
  82. a_word = string(words[keywordsLimit:])
  83. }
  84. } else {
  85. b_word = word
  86. }
  87. a_word = strings.TrimSpace(a_word)
  88. s_word = MatchSpace.ReplaceAllString(b_word, " ")
  89. return
  90. }
  91. func HttpEs(ques, analyzer, esAddress string) string {
  92. return es.Analyze(ques, "bidding", analyzer)
  93. }
  94. // 发送邮箱验证码
  95. func SendMailIdentCode(to, code string, auth []*mail.GmailAuth) bool {
  96. html := fmt.Sprintf(`<div>
  97. <div>
  98. %s,您好!
  99. </div>
  100. <div style="padding: 20px 70px 10px 70px;">
  101. <p>您正在进行绑定邮箱地址验证,请在邮件验证码输入框输入下方验证码:</p>
  102. <span style="font-weight: bold;font-size: x-large;">%s</span>
  103. <p>请勿向任何人泄露您收到的验证码。</p>
  104. <p>如果您没有使用剑鱼标讯,请忽略此邮件。</p>
  105. <p>此为系统邮件,请勿回复。</p>
  106. <p>如有疑问,请联系客服 400-108-6670。</p>
  107. </div>
  108. <div>
  109. <p>此致</p>
  110. <p>剑鱼标讯</p>
  111. </div>
  112. </div>`, to, code)
  113. for k, v := range auth {
  114. if mail.GSendMail("剑鱼标讯", to, "", "", "剑鱼标讯邮箱校验", html, "", "", v) {
  115. log.Println(to, fmt.Sprintf("使用%s发送邮件成功", v.User))
  116. return true
  117. }
  118. if k < len(auth)-1 {
  119. log.Println(to, fmt.Sprintf("使用%s发送邮件失败!3s后使用其他邮箱尝试", v.User))
  120. } else {
  121. log.Println(to, fmt.Sprintf("使用%s发送邮件失败!", v.User))
  122. }
  123. time.Sleep(time.Second * 3)
  124. }
  125. return false
  126. }
  127. func SendSMS(r *http.Request, address, mobile string, params ...string) {
  128. sms.SendSms(util.GetIp(r), address, "01", mobile, params...)
  129. return
  130. }
  131. // 发送验证码
  132. // 增加sessionKey字段 更换手机号防止绕过身份校验
  133. func SendPhoneIdentCode(r *http.Request, address, phone string, session *httpsession.Session, sessionKey ...string) bool {
  134. sessionKeyFlag := defaultPhoneFlag
  135. if len(sessionKey) > 0 && sessionKey[0] != "" {
  136. sessionKeyFlag = sessionKey[0]
  137. }
  138. lastSentTime := util.Int64All(session.Get(fmt.Sprintf("%sTime", sessionKeyFlag)))
  139. //60秒之内不允许重复发
  140. if lastSentTime > 0 && time.Now().Unix()-lastSentTime <= 60 {
  141. return false
  142. }
  143. s_ranNum := util.GetRandom(6) //生成随机数
  144. //s_ranNum = "111111"
  145. session.Set(fmt.Sprintf("%sValue", sessionKeyFlag), s_ranNum)
  146. session.Set(fmt.Sprintf("%sKey", sessionKeyFlag), phone)
  147. session.Set(fmt.Sprintf("%sTime", sessionKeyFlag), time.Now().Unix())
  148. //发送短信
  149. log.Println("短信验证码", phone, s_ranNum)
  150. SendSMS(r, address, phone, s_ranNum)
  151. return true
  152. }
  153. const (
  154. defaultPhoneFlag = "identCode"
  155. ExperienceSign = "EXPERIENCESIGN"
  156. )
  157. // 短信验证码校验
  158. func CheckPhoneIdent(session *httpsession.Session, code string, sessionKey ...string) string {
  159. sessionKeyFlag := defaultPhoneFlag
  160. if len(sessionKey) > 0 && sessionKey[0] != "" {
  161. sessionKeyFlag = sessionKey[0]
  162. }
  163. identCodeValue, _ := session.Get(fmt.Sprintf("%sValue", sessionKeyFlag)).(string)
  164. if identCodeValue != "" && identCodeValue == code {
  165. identCodeKey, _ := session.Get(fmt.Sprintf("%sKey", sessionKeyFlag)).(string)
  166. ClearPhoneIdentSession(session, sessionKey...)
  167. return identCodeKey
  168. }
  169. return ""
  170. }
  171. // 删除短信验证码有关的session
  172. func ClearPhoneIdentSession(session *httpsession.Session, sessionKey ...string) {
  173. sessionKeyFlag := defaultPhoneFlag
  174. if len(sessionKey) > 0 && sessionKey[0] != "" {
  175. sessionKeyFlag = sessionKey[0]
  176. }
  177. session.Del(fmt.Sprintf("%sValue", sessionKeyFlag))
  178. session.Del(fmt.Sprintf("%sKey", sessionKeyFlag))
  179. session.Del(fmt.Sprintf("%sTime", sessionKeyFlag))
  180. }
  181. // 邮箱校验
  182. func IsEmail(value string) bool {
  183. return EmailPattern.MatchString(value)
  184. }
  185. // 手机号校验
  186. func IsPhone(phone string) bool {
  187. return PhoneReg.MatchString(phone)
  188. }
  189. // 获取信息行业
  190. func Getindustrys(industryname string, mongodb MongodbSim) (industry map[string][]string, sortArray []string) {
  191. industry = map[string][]string{}
  192. sortArray = []string{}
  193. classdata, ok1 := mongodb.FindOneByField("rc_task", `{"s_name":"`+industryname+`"}`, `{"s_class":1}`)
  194. if ok1 && len(*classdata) > 0 {
  195. classid := ""
  196. if util.ObjToString((*classdata)["s_class"]) != "" {
  197. classids := strings.Split(util.ObjToString((*classdata)["s_class"]), ",")
  198. for k, v := range classids {
  199. if k > 0 {
  200. classid += `,`
  201. }
  202. classid += `"` + v + `"`
  203. }
  204. }
  205. industryData, ok := mongodb.Find("rc_rule", `{"s_pid":{"$ne":""},"s_classid":{"$in":[`+classid+`]}}`, `{"i_order":1}`, `{"_id":1,"s_name":1}`, false, -1, -1)
  206. if ok && industryData != nil && len(*industryData) > 0 {
  207. for _, v := range *industryData {
  208. fatFlag := 0
  209. industryname, _ := v["s_name"].(string)
  210. if strings.Contains(industryname, "_") {
  211. fat := strings.Split(industryname, "_")[0]
  212. child := strings.Split(industryname, "_")[1]
  213. if len(industry[fat]) == 0 {
  214. sortArray = append(sortArray, fat)
  215. }
  216. for _, fv := range industry[fat] {
  217. if fv == strings.Trim(child, " ") {
  218. fatFlag = 1
  219. break
  220. }
  221. }
  222. if fatFlag != 1 {
  223. industry[fat] = append(industry[fat], child)
  224. }
  225. }
  226. }
  227. }
  228. }
  229. return industry, sortArray
  230. }
  231. // 对应月份
  232. func GetMonth(mon string) int {
  233. month := map[string]int{
  234. "January": 1,
  235. "February": 2,
  236. "March": 3,
  237. "April": 4,
  238. "May": 5,
  239. "June": 6,
  240. "July": 7,
  241. "August": 8,
  242. "September": 9,
  243. "October": 10,
  244. "November": 11,
  245. "December": 12,
  246. }
  247. return month[mon]
  248. }
  249. // value unlimited 并发限制登陆用户
  250. func LoginRedisKey(userid string) string {
  251. return fmt.Sprintf("unlimited_%s", userid)
  252. }
  253. // 获取loginSess
  254. func GetLoginSess(userid string) []string {
  255. key := LoginRedisKey(userid)
  256. if data, ok := redis.Get("other", key).([]interface{}); ok {
  257. return util.ObjArrToStringArr(data)
  258. }
  259. return []string{}
  260. }
  261. // 判断是否在内
  262. func IsInLoginSess(key string, arr []string) bool {
  263. for _, v := range arr {
  264. if key == v {
  265. return true
  266. }
  267. }
  268. return false
  269. }
  270. type TtlMap struct {
  271. key string //sessionid
  272. value int //ttl
  273. }
  274. type AppLoginPush struct {
  275. JgPushId string `json:"jpushId"`
  276. OtherPushId string `json:"opushId"`
  277. PhoneType string `json:"phoneType"`
  278. }
  279. // 更新存储用户sessionid的队列 【sessionid ttl小于三天的清除】 key:sessionid
  280. func PutLoginSess(mongodb MongodbSim, apppushRpc, key, userid string, limit, max int) bool {
  281. value := GetLoginSess(userid)
  282. if !IsInLoginSess(key, value) {
  283. value = append(value, key)
  284. }
  285. ttlmap := []TtlMap{}
  286. if len(value) >= int(limit*max/100) {
  287. new_value := []string{}
  288. //如果已存的session大于限制 则清除三天后到期的session
  289. for _, vv := range value {
  290. ttl := redis.GetTTL("session", vv)
  291. if ttl <= 86400*1 && ttl != -1 {
  292. // if ttl <= 600 && ttl != -1 {
  293. if ok := redis.Del("session", vv); ok {
  294. LoginOutPush(mongodb, userid, vv, apppushRpc)
  295. log.Println(fmt.Sprintf("%s用户的sessionid 到期时间还有%v 小于三天 清除 %s", userid, ttl, vv))
  296. }
  297. continue
  298. }
  299. new_value = append(new_value, vv)
  300. ttlmap = append(ttlmap, TtlMap{vv, int(ttl)})
  301. }
  302. value = new_value
  303. }
  304. //清除并发最大限制的某个sessionid
  305. if len(value) > max {
  306. //排序 获取马上过期的session 清除
  307. sort.Slice(ttlmap, func(i, j int) bool {
  308. return ttlmap[i].value < ttlmap[j].value
  309. })
  310. if len(ttlmap) > 0 {
  311. //清除sessionid
  312. delId := ttlmap[0].key
  313. redis.Del("session", delId)
  314. value = removeArr(value, delId)
  315. LoginOutPush(mongodb, userid, delId, apppushRpc)
  316. log.Println(fmt.Sprintf("%s用户的sessionid 超过最大限制 清除 %s ,到期时间%v", userid, delId, ttlmap[0].value))
  317. for _, v := range ttlmap {
  318. log.Println(v.key, "===", v.value)
  319. }
  320. }
  321. }
  322. return redis.Put("other", LoginRedisKey(userid), value, -1)
  323. }
  324. // 清除数组中的s
  325. func removeArr(arr []string, s string) []string {
  326. result := []string{}
  327. for _, v := range arr {
  328. if v == s {
  329. continue
  330. }
  331. result = append(result, v)
  332. }
  333. return result
  334. }
  335. func LoginOutPush(mongodb MongodbSim, userid, sessid, apppushRpc string) {
  336. rediskey := fmt.Sprintf("app_%s", sessid)
  337. r := redis.Get("other", rediskey)
  338. if r == nil {
  339. return
  340. }
  341. arr, err := json.Marshal(r)
  342. if err != nil {
  343. log.Println("json Marshal err:", err)
  344. }
  345. apppush := AppLoginPush{}
  346. // 反序列化
  347. err2 := json.Unmarshal(arr, &apppush)
  348. if err2 != nil {
  349. log.Println("json Unmarshal err:", err)
  350. }
  351. if apppush.JgPushId == "" {
  352. return
  353. }
  354. mongodb.UpdateById("user", userid, map[string]interface{}{
  355. "$unset": map[string]interface{}{"s_jpushid": "", "s_opushid": ""},
  356. "$addToSet": map[string]interface{}{"a_jpushid": apppush.JgPushId},
  357. })
  358. //
  359. log.Println("多账号登陆:", userid, apppush.PhoneType, apppush.JgPushId, apppush.OtherPushId, "踢人下线")
  360. ok := qrpc.AppPush(apppushRpc, map[string]interface{}{
  361. "type": "signOut",
  362. "descript": "您的账号在其他设备登录,如有需要请重新登录。",
  363. "jgPushId": apppush.JgPushId,
  364. "otherPushId": apppush.OtherPushId,
  365. "phoneType": apppush.PhoneType,
  366. "userId": userid,
  367. })
  368. log.Println("ok:", ok)
  369. }
  370. // session数组清除某个value[针对多账号同时在线的方法、退出登录时调用]
  371. func DelUnlimitSessionId(sessid, userid string) []string {
  372. sessArr := GetLoginSess(userid)
  373. newArr := []string{}
  374. for _, v := range sessArr {
  375. if v == sessid {
  376. continue
  377. }
  378. newArr = append(newArr, v)
  379. }
  380. return newArr
  381. }
  382. // 获取当天结束时间 单位秒
  383. func GetExpire() int {
  384. t, _ := time.ParseInLocation(Date_Short_Layout, time.Now().AddDate(0, 0, 1).Format(Date_Short_Layout), time.Local)
  385. t2, _ := time.ParseInLocation(Date_Full_Layout, time.Now().Format(Date_Full_Layout), time.Local)
  386. return int(t.Unix() - t2.Unix())
  387. }
  388. func TimeProcessing(hour interface{}, duration int) time.Time {
  389. todayZero, _ := time.ParseInLocation(Date_Full_Layout, fmt.Sprint(hour), time.Local)
  390. mm, _ := time.ParseDuration(fmt.Sprint(duration) + "m")
  391. t := todayZero.Add(mm)
  392. return t
  393. }
  394. // 清除用户权益缓存、菜单缓存
  395. func ClearUserCache(middleground *Middleground, positionId int64) {
  396. middleground.UserCenter.WorkDesktopClearUserInfo(pb.WorkDesktopClearUserInfoReq{
  397. PositionId: fmt.Sprint(positionId),
  398. })
  399. middleground.PowerCheckCenter.DelCheckRedis("10000", positionId)
  400. }
  401. // 关键词分词处理
  402. func KeywordsProcessing(keywords, originalWord, sep string) string {
  403. keywords = MatchSpace.ReplaceAllString(keywords, " ")
  404. if keywords == "" || len(strings.Split(keywords, sep)) == 1 {
  405. return keywords
  406. }
  407. if originalWord == "" {
  408. originalWord = strings.ReplaceAll(keywords, sep, "")
  409. }
  410. var newWords = make([]string, 0, 0)
  411. if keywords != "" && len(strings.Split(keywords, sep)) > 1 {
  412. var words = strings.Split(keywords, sep)
  413. for k := 0; k < len(words); k++ {
  414. v := words[k]
  415. //连续性空格
  416. if len([]rune(v)) == 0 {
  417. continue
  418. }
  419. if len([]rune(v)) == 1 {
  420. //compare
  421. if k == 0 { //first
  422. newWord := v + words[k+1]
  423. if strings.Contains(originalWord, newWord) { //组合后 必须包含
  424. words[k+1] = newWord
  425. }
  426. } else if k == len(words)-1 { //last
  427. newWord := newWords[len(newWords)-1] + v
  428. if strings.Contains(originalWord, newWord) {
  429. newWords[len(newWords)-1] = newWord
  430. }
  431. } else {
  432. if len([]rune(newWords[len(newWords)-1])) < len([]rune(words[k+1])) {
  433. newWord := newWords[len(newWords)-1] + v
  434. if strings.Contains(originalWord, newWord) {
  435. newWords[len(newWords)-1] = newWord
  436. } else {
  437. newWord = v + words[k+1]
  438. if strings.Contains(originalWord, newWord) { //组合后 必须包含
  439. words[k+1] = newWord
  440. }
  441. }
  442. } else {
  443. newWord := v + words[k+1]
  444. if strings.Contains(originalWord, newWord) { //组合后 必须包含
  445. words[k+1] = newWord
  446. } else {
  447. newWord = newWords[len(newWords)-1] + v
  448. if strings.Contains(originalWord, newWord) {
  449. newWords[len(newWords)-1] = newWord
  450. }
  451. }
  452. }
  453. }
  454. } else {
  455. newWords = append(newWords, v)
  456. }
  457. }
  458. }
  459. return strings.Join(newWords, sep)
  460. }
  461. // 行业分类 其它分类处理
  462. var industryQT = "其它"
  463. func IndustryHandle(industry string) (it []string) {
  464. for _, v := range strings.Split(industry, ",") {
  465. if strings.Contains(v, "其他") {
  466. var iqt = industryQT
  467. if len(strings.Split(v, "_")) > 1 {
  468. iqt = fmt.Sprintf("%s_%s", strings.Split(v, "_")[0], industryQT)
  469. }
  470. it = append(it, iqt)
  471. }
  472. }
  473. return
  474. }