emoji-pack.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package main
  2. import (
  3. "encoding/json"
  4. "io"
  5. "net/http"
  6. "net/url"
  7. "os"
  8. "path/filepath"
  9. )
  10. type EmojiPack struct {
  11. Files map[string]string `json:"files"`
  12. Metadata EmojiPackMetadata `json:"pack"`
  13. }
  14. type EmojiPackMetadata struct {
  15. License string `json:"license,omitempty"`
  16. Homepage string `json:"homepage,omitempty"`
  17. Description string `json:"description,omitempty"`
  18. Fallback string `json:"fallback-src,omitempty"`
  19. FallbackChecksum string `json:"fallback-src-sha256,omitempty"`
  20. AllowSharing bool `json:"share-files,omitempty"`
  21. }
  22. func NewEmojiPack() EmojiPack {
  23. p := EmojiPack{}
  24. p.Files = map[string]string{}
  25. p.Metadata = EmojiPackMetadata{}
  26. return p
  27. }
  28. func (p *EmojiPack) SetFiles(es Emojis) {
  29. for _, e := range es {
  30. k := e.Shortcode
  31. if k == "" {
  32. k = e.Name
  33. }
  34. p.Files[k] = e.Url
  35. }
  36. }
  37. func (p *EmojiPack) Json() ([]byte, error) {
  38. return json.Marshal(p)
  39. }
  40. type EmojiResult struct {
  41. Shortcode string
  42. File string
  43. Error error
  44. }
  45. func (p *EmojiPack) GenerateEmojiPack(outputDir string) error {
  46. if _, err := os.Stat(outputDir); os.IsNotExist(err) {
  47. if err = mkdir(outputDir); err != nil {
  48. return err
  49. }
  50. }
  51. c := make(chan EmojiResult, 20)
  52. limitCh := make(chan struct{}, 20)
  53. defer close(c)
  54. defer close(limitCh)
  55. for code, ru := range p.Files {
  56. limitCh <- struct{}{}
  57. go downloadEmojiFile(outputDir, code, ru, c)
  58. <-limitCh
  59. }
  60. files := map[string]string{}
  61. for i := 0; i < len(p.Files); i++ {
  62. result := <-c
  63. if result.Error != nil {
  64. continue
  65. }
  66. files[result.Shortcode] = result.File
  67. }
  68. p.Files = files
  69. // generate pack.json
  70. f, err := os.Create(filepath.Join(outputDir, "pack.json"))
  71. if err != nil {
  72. return err
  73. }
  74. defer f.Close()
  75. b, err := p.Json()
  76. if err != nil {
  77. return err
  78. }
  79. _, err = f.Write(b)
  80. return err
  81. }
  82. func mkdir(name string) error {
  83. err := os.Mkdir(name, 0777)
  84. if os.IsNotExist(err) {
  85. mkdir(filepath.Dir(name))
  86. return os.Mkdir(name, 0777)
  87. }
  88. return err
  89. }
  90. func downloadEmojiFile(outputDir string, shortcode string, fileUrl string, result chan EmojiResult) {
  91. r := EmojiResult{
  92. Shortcode: shortcode,
  93. }
  94. defer func() { result <- r }()
  95. var u *url.URL
  96. u, r.Error = url.Parse(fileUrl)
  97. if r.Error != nil {
  98. return
  99. }
  100. var resp *http.Response
  101. resp, r.Error = http.Get(u.String())
  102. if r.Error != nil {
  103. return
  104. }
  105. defer resp.Body.Close()
  106. var ueu string
  107. ueu, r.Error = url.PathUnescape(u.String())
  108. if r.Error != nil {
  109. return
  110. }
  111. r.File = shortcode + filepath.Ext(filepath.Base(ueu))
  112. var f *os.File
  113. f, r.Error = os.Create(filepath.Join(outputDir, r.File))
  114. if r.Error != nil {
  115. return
  116. }
  117. defer f.Close()
  118. _, r.Error = io.Copy(f, resp.Body)
  119. }