emoji-pack.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. p.Files[e.Shortcode] = e.Url
  31. }
  32. }
  33. func (p *EmojiPack) Json() ([]byte, error) {
  34. return json.Marshal(p)
  35. }
  36. type EmojiResult struct {
  37. Shortcode string
  38. File string
  39. Error error
  40. }
  41. func (p *EmojiPack) GenerateEmojiPack(outputDir string) error {
  42. if _, err := os.Stat(outputDir); os.IsNotExist(err) {
  43. if err = mkdir(outputDir); err != nil {
  44. return err
  45. }
  46. }
  47. c := make(chan EmojiResult, 30)
  48. limitCh := make(chan struct{}, 20)
  49. defer close(c)
  50. defer close(limitCh)
  51. for code, ru := range p.Files {
  52. go downloadEmojiFile(outputDir, code, ru, c, limitCh)
  53. }
  54. files := map[string]string{}
  55. for i := 0; i < len(p.Files); i++ {
  56. result := <-c
  57. if result.Error != nil {
  58. continue
  59. }
  60. files[result.Shortcode] = result.File
  61. }
  62. p.Files = files
  63. // generate pack.json
  64. f, err := os.Create(filepath.Join(outputDir, "pack.json"))
  65. if err != nil {
  66. return err
  67. }
  68. defer f.Close()
  69. b, err := p.Json()
  70. if err != nil {
  71. return err
  72. }
  73. _, err = f.Write(b)
  74. return err
  75. }
  76. func mkdir(name string) error {
  77. err := os.Mkdir(name, 0777)
  78. if os.IsNotExist(err) {
  79. mkdir(filepath.Dir(name))
  80. return os.Mkdir(name, 0777)
  81. }
  82. return err
  83. }
  84. func downloadEmojiFile(outputDir string, shortcode string, fileUrl string, result chan EmojiResult, limit chan struct{}) {
  85. limit <- struct{}{}
  86. r := EmojiResult{
  87. Shortcode: shortcode,
  88. }
  89. var u *url.URL
  90. u, r.Error = url.Parse(fileUrl)
  91. if r.Error != nil {
  92. <-limit
  93. result <- r
  94. return
  95. }
  96. var resp *http.Response
  97. resp, r.Error = http.Get(u.String())
  98. if r.Error != nil {
  99. <-limit
  100. result <- r
  101. return
  102. }
  103. defer resp.Body.Close()
  104. var ueu string
  105. ueu, r.Error = url.PathUnescape(u.String())
  106. if r.Error != nil {
  107. <-limit
  108. result <- r
  109. return
  110. }
  111. r.File = 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. <-limit
  116. result <- r
  117. return
  118. }
  119. defer f.Close()
  120. _, r.Error = io.Copy(f, resp.Body)
  121. <-limit
  122. result <- r
  123. }