node_strings.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. package core
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math"
  6. "math/rand"
  7. "net/url"
  8. "path/filepath"
  9. "regexp"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "github.com/cdle/sillyplus/emoji"
  14. "github.com/cdle/sillyplus/utils"
  15. )
  16. var mystr = &Strings{}
  17. type Strings struct {
  18. UUID string
  19. }
  20. type H map[string]interface{}
  21. func (sender *Strings) Diff(a, b []interface{}) []interface{} {
  22. m := make(map[interface{}]bool)
  23. c := make([]interface{}, 0)
  24. for _, v := range b {
  25. m[v] = true
  26. }
  27. for _, v := range a {
  28. if !m[v] {
  29. c = append(c, v)
  30. }
  31. }
  32. return c
  33. }
  34. func similarity(str1, str2 string) int {
  35. str1 = strings.ToLower(str1)
  36. str2 = strings.ToLower(str2)
  37. ml := 2
  38. ws := []string{}
  39. tp := []rune{}
  40. for _, r := range str2 {
  41. tp = append(tp, r)
  42. if !strings.Contains(str1, string(tp)) {
  43. tp = tp[:len(tp)-1]
  44. if len(tp) > ml {
  45. ws = append(ws, string(tp))
  46. }
  47. tp = []rune{r}
  48. }
  49. }
  50. if strings.Contains(str1, string(tp)) {
  51. ws = append(ws, string(tp))
  52. }
  53. return len(strings.Join(ws, ""))
  54. }
  55. func (sender *Strings) Similarity(str1, str2 string) float64 {
  56. if str1 == "" || str2 == "" {
  57. return 0
  58. }
  59. max := math.Max(
  60. float64(similarity(str1, str2))/float64(len(str2)),
  61. float64(similarity(str2, str1))/float64(len(str1)),
  62. )
  63. b := float64(len(str2)) / float64(len(str1))
  64. if b > 1 {
  65. b = 1 / b
  66. }
  67. return max * ((b + 1) / 2)
  68. }
  69. func (sender *Strings) HansSimilarity(str1, str2 string) float64 {
  70. if str1 == str2 {
  71. return 1
  72. }
  73. return sender.Similarity(str1, str2)
  74. }
  75. func (sender *Strings) ExtractHans(text string) []string {
  76. return regexp.MustCompile(`[\p{Han}]+`).FindAllString(text, -1)
  77. }
  78. func (sender *Strings) Intersect(a, b interface{}) interface{} {
  79. // 判断是否为字符串类型
  80. if sa, ok := a.(string); ok {
  81. if sb, ok := b.(string); ok {
  82. // 如果是字符串类型,则寻找共同拥有的最长字符串
  83. var longest string
  84. for i := 0; i < len(sa); i++ {
  85. for j := i + 1; j <= len(sa); j++ {
  86. substr := sa[i:j]
  87. if strings.Contains(sb, substr) && len(substr) > len(longest) {
  88. longest = substr
  89. }
  90. }
  91. }
  92. return longest
  93. }
  94. }
  95. // 否则,使用普通的交集算法
  96. m := make(map[interface{}]bool)
  97. c := make([]interface{}, 0)
  98. for _, v := range a.([]interface{}) {
  99. m[v] = true
  100. }
  101. for _, v := range b.([]interface{}) {
  102. if m[v] {
  103. c = append(c, v)
  104. }
  105. }
  106. return c
  107. }
  108. func (sender *Strings) Union(a, b []interface{}) []interface{} {
  109. m := make(map[interface{}]bool)
  110. c := make([]interface{}, 0)
  111. for _, v := range a {
  112. m[v] = true
  113. c = append(c, v)
  114. }
  115. for _, v := range b {
  116. if !m[v] {
  117. c = append(c, v)
  118. }
  119. }
  120. return c
  121. }
  122. func (sender *Strings) Random(length int, substr string) string {
  123. ws := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  124. if substr != "" {
  125. ws = substr
  126. }
  127. rand.Seed(time.Now().UnixNano())
  128. letters := []rune(ws)
  129. b := make([]rune, length)
  130. for i := range b {
  131. b[i] = letters[rand.Intn(len(letters))]
  132. }
  133. return string(b)
  134. }
  135. func (sender *Strings) JoinFilepath(elem ...string) string {
  136. return filepath.Join(elem...)
  137. }
  138. func ForeachObject(m map[string]interface{}, callback func(key, value interface{}) bool) bool {
  139. for k, v := range m {
  140. switch v := v.(type) {
  141. case map[string]interface{}:
  142. if ForeachObject(v, callback) {
  143. return true
  144. }
  145. case []interface{}:
  146. for _, u := range v {
  147. if um, ok := u.(map[string]interface{}); ok {
  148. if ForeachObject(um, callback) {
  149. return true
  150. }
  151. }
  152. }
  153. case string:
  154. if callback(k, v) {
  155. return true
  156. }
  157. }
  158. }
  159. return false
  160. }
  161. func (sender *Strings) Trim(s, cutset string) string {
  162. return strings.Trim(s, cutset)
  163. }
  164. func (sender *Strings) TrimLeft(s, cutset string) string {
  165. return strings.TrimLeft(s, cutset)
  166. }
  167. func (sender *Strings) TrimRight(s, cutset string) string {
  168. return strings.TrimRight(s, cutset)
  169. }
  170. func (sender *Strings) Filename(path string) string {
  171. re := regexp.MustCompile(`[\\/]+`)
  172. parts := re.Split(path, -1)
  173. filename := parts[len(parts)-1]
  174. return filename
  175. }
  176. func (sender *Strings) Dir(path string) string {
  177. re := regexp.MustCompile(`[\\/]+`)
  178. parts := re.Split(path, -1)
  179. filename := parts[len(parts)-1]
  180. dir := path[:len(path)-len(filename)]
  181. dir = filepath.Clean(dir)
  182. return dir
  183. }
  184. func (sender *Strings) Contains(s string, substr interface{}) bool {
  185. switch substr := substr.(type) {
  186. case string:
  187. return strings.Contains(s, substr)
  188. case []string:
  189. for _, sub := range substr {
  190. if strings.Contains(s, sub) {
  191. return true
  192. }
  193. }
  194. return false
  195. case []interface{}:
  196. for _, sub := range substr {
  197. if strings.Contains(s, sub.(string)) {
  198. return true
  199. }
  200. }
  201. return false
  202. }
  203. return false
  204. }
  205. func (sender *Strings) ToLower(s string) string {
  206. return strings.ToLower(s)
  207. }
  208. func (sender *Strings) ToUpper(s string) string {
  209. return strings.ToUpper(s)
  210. }
  211. func (sender *Strings) Remove(ss []string, s string) []string {
  212. return utils.Remove(ss, s)
  213. }
  214. func (sender *Strings) Append(ss []string, s string) []string {
  215. return append(ss, s)
  216. }
  217. func (sender *Strings) HasPrefix(s, substr string) bool {
  218. return strings.HasPrefix(s, substr)
  219. }
  220. func (sender *Strings) HasSuffix(s, substr string) bool {
  221. return strings.HasSuffix(s, substr)
  222. }
  223. func (sender *Strings) Replace(s_ interface{}, old string, new string, n int) interface{} {
  224. switch s := s_.(type) {
  225. case string:
  226. if n == 0 {
  227. n = -1
  228. }
  229. return strings.Replace(s, old, new, n)
  230. case []string:
  231. for i := range s {
  232. if s[i] == old {
  233. s[i] = new
  234. }
  235. }
  236. return s
  237. case []interface{}:
  238. for i := range s {
  239. if s[i] == old {
  240. s[i] = new
  241. }
  242. }
  243. return s
  244. }
  245. return ""
  246. }
  247. func (sender *Strings) ReplaceAll(s string, old string, new string) string {
  248. return strings.ReplaceAll(s, old, new)
  249. }
  250. func (sender *Strings) Split(s string, sep string, n int) []string {
  251. return strings.SplitN(s, sep, n)
  252. }
  253. func (sender *Strings) BuildQuery(params map[string]interface{}) string {
  254. return sender.EncodeQueryString(params)
  255. }
  256. func (sender *Strings) EncodeQueryString(params map[string]interface{}) string {
  257. var buf bytes.Buffer
  258. for key, value := range params {
  259. if buf.Len() > 0 {
  260. buf.WriteByte('&')
  261. }
  262. buf.WriteString(url.QueryEscape(key))
  263. buf.WriteByte('=')
  264. switch v := value.(type) {
  265. case string:
  266. buf.WriteString(url.QueryEscape(v))
  267. case int:
  268. buf.WriteString(strconv.Itoa(v))
  269. case int64:
  270. buf.WriteString(strconv.Itoa(int(v)))
  271. case int32:
  272. buf.WriteString(strconv.Itoa(int(v)))
  273. case bool:
  274. buf.WriteString(strconv.FormatBool(v))
  275. default:
  276. buf.WriteString(url.QueryEscape(fmt.Sprintf("%v", v)))
  277. }
  278. }
  279. return buf.String()
  280. }
  281. func (sender *Strings) ParseQuery(querystring string) map[string]interface{} {
  282. return sender.DecodeQueryString(querystring)
  283. }
  284. func (sender *Strings) DecodeQueryString(querystring string) map[string]interface{} {
  285. u, err := url.Parse(querystring)
  286. if err != nil {
  287. panic(err)
  288. }
  289. params := make(map[string]interface{})
  290. for key, values := range u.Query() {
  291. if len(values) > 0 {
  292. value := values[0]
  293. // if intValue, err := strconv.Atoi(value); err == nil {
  294. // params[key] = intValue
  295. // } else if boolValue, err := strconv.ParseBool(value); err == nil {
  296. // params[key] = boolValue
  297. // } else {
  298. // params[key] = value
  299. // }
  300. params[key] = value
  301. }
  302. }
  303. return params
  304. }
  305. func (sender *Strings) HideCQEmoji(text string) map[string]interface{} {
  306. i := 0
  307. var ms = map[string]string{}
  308. text = regexp.MustCompile(`\[CQ:(\w+)(.*?)\]`).ReplaceAllStringFunc(text, func(s string) string {
  309. v := fmt.Sprintf("#%d#", i)
  310. i++
  311. ms[v] = s
  312. return v
  313. })
  314. text = emoji.ReplaceEmojisWithFunc(text, func(e emoji.Emoji) string {
  315. v := fmt.Sprintf("#%d#", i)
  316. i++
  317. ms[v] = e.Character
  318. return v
  319. })
  320. return map[string]interface{}{
  321. "text": text,
  322. "recover": func(text string) string {
  323. return regexp.MustCompile(`#\d{1,4}#`).ReplaceAllStringFunc(text, func(s string) string {
  324. return ms[s]
  325. })
  326. },
  327. }
  328. }
  329. // 构建CQ码
  330. func (sender *Strings) BuildCQCode(cqType string, params map[string]interface{}, prefix string) string {
  331. if prefix == "" {
  332. prefix = "CQ"
  333. }
  334. var sb strings.Builder
  335. sb.WriteString("[" + prefix + ":" + cqType)
  336. for k, v := range params {
  337. sb.WriteString(", ")
  338. sb.WriteString(k)
  339. sb.WriteString("=")
  340. sb.WriteString(fmt.Sprintf("%v", v))
  341. }
  342. sb.WriteString("]")
  343. return sb.String()
  344. }
  345. // 将含有 CQ码 的文本解析成文本和 CQ 对象数组
  346. func (sender *Strings) ParseCQText(text string, prefix string) []interface{} {
  347. if prefix == "" {
  348. prefix = "CQ"
  349. }
  350. cqRegex := regexp.MustCompile(`\[` + prefix + `:(\w+)(.*?)\]`)
  351. cqMatches := cqRegex.FindAllStringSubmatch(text, -1)
  352. result := make([]interface{}, 0, len(cqMatches)*2+1)
  353. // 依次解析 CQ 码和文本
  354. lastIndex := 0
  355. for _, match := range cqMatches {
  356. // 添加 CQ 码前的文本
  357. if matchIndex := strings.Index(text[lastIndex:], match[0]); matchIndex > 0 {
  358. result = append(result, text[lastIndex:lastIndex+matchIndex])
  359. lastIndex += matchIndex
  360. }
  361. // 解析 CQ 码
  362. params := make(map[string]string)
  363. paramRegex := regexp.MustCompile(`(\w+)=([^,]+)`)
  364. paramMatches := paramRegex.FindAllStringSubmatch(match[2], -1)
  365. for _, paramMatch := range paramMatches {
  366. params[paramMatch[1]] = strings.TrimSpace(paramMatch[2])
  367. }
  368. result = append(result, CQ{
  369. Type: match[1],
  370. Params: params,
  371. })
  372. lastIndex += len(match[0])
  373. }
  374. // 添加最后一个 CQ 码后的文本
  375. if lastIndex < len(text) {
  376. result = append(result, text[lastIndex:])
  377. }
  378. return result
  379. }
  380. // CQ 对象
  381. type CQ struct {
  382. Type string
  383. Params map[string]string
  384. }
  385. // 将 CQ 对象数组转换回原始文本
  386. func (sender *Strings) StringifyCQText(cqList []interface{}, prefix string) string {
  387. if prefix == "" {
  388. prefix = "CQ"
  389. }
  390. var sb strings.Builder
  391. for _, item := range cqList {
  392. switch item := item.(type) {
  393. case string:
  394. sb.WriteString(item)
  395. case CQ:
  396. sb.WriteString(fmt.Sprintf("["+prefix+":%s", item.Type))
  397. for k, v := range item.Params {
  398. sb.WriteString(fmt.Sprintf(",%s=%s", k, v))
  399. }
  400. sb.WriteString("]")
  401. case map[string]interface{}:
  402. cq := CQ{
  403. Type: item["Type"].(string),
  404. Params: convertParams(item["Params"].(map[string]interface{})),
  405. }
  406. sb.WriteString(fmt.Sprintf("["+prefix+":%s", cq.Type))
  407. for k, v := range cq.Params {
  408. sb.WriteString(fmt.Sprintf(",%s=%s", k, v))
  409. }
  410. sb.WriteString("]")
  411. }
  412. }
  413. return sb.String()
  414. }
  415. // 将 map[string]interface{} 类型的 params 转换为 map[string]string 类型
  416. func convertParams(params map[string]interface{}) map[string]string {
  417. result := make(map[string]string)
  418. for k, v := range params {
  419. if s, ok := v.(string); ok {
  420. result[k] = s
  421. }
  422. }
  423. return result
  424. }
  425. func (sender *Strings) ReplaceEmojis(str string, f func([]string) string) string {
  426. return emoji.ReplaceEmojisWithFunc(str, func(e emoji.Emoji) string {
  427. return f(e.CodePoint2)
  428. })
  429. }
  430. // `\[emoji=([0-9A-Z]{4})\]`
  431. func (sender *Strings) ReplaceToEmojis(str string, pattern string) string {
  432. return emoji.ReplaceToEmojis(str, pattern)
  433. }
  434. func (sender *Strings) ExtractAddress(input string) string {
  435. return regexp.MustCompile(`http[s]?://[\w.]+:?\d*`).FindString(input)
  436. }
  437. func (sender *Strings) Unique(str ...interface{}) []string {
  438. return utils.Unique(str...)
  439. }
  440. func (sender *Strings) Longest(args ...interface{}) string {
  441. var longest string
  442. for _, arg := range args {
  443. switch v := arg.(type) {
  444. case string:
  445. if len(v) > len(longest) {
  446. longest = v
  447. }
  448. case []string:
  449. for _, s := range v {
  450. if len(s) > len(longest) {
  451. longest = s
  452. }
  453. }
  454. case []interface{}:
  455. for _, s := range v {
  456. if len(s.(string)) > len(longest) {
  457. longest = s.(string)
  458. }
  459. }
  460. case [][]string:
  461. for _, s := range v {
  462. longest = sender.Longest(s)
  463. }
  464. case [][]interface{}:
  465. for _, s := range v {
  466. longest = sender.Longest(s)
  467. }
  468. }
  469. }
  470. return longest
  471. }
  472. func (sender *Strings) Shortest(args ...interface{}) string {
  473. var longest string
  474. for _, arg := range args {
  475. switch v := arg.(type) {
  476. case string:
  477. if len(v) < len(longest) {
  478. longest = v
  479. }
  480. case []string:
  481. for _, s := range v {
  482. if len(s) < len(longest) {
  483. longest = s
  484. }
  485. }
  486. case []interface{}:
  487. for _, s := range v {
  488. if len(s.(string)) < len(longest) {
  489. longest = s.(string)
  490. }
  491. }
  492. case [][]string:
  493. for _, s := range v {
  494. longest = sender.Shortest(s)
  495. }
  496. case [][]interface{}:
  497. for _, s := range v {
  498. longest = sender.Shortest(s)
  499. }
  500. }
  501. }
  502. return longest
  503. }