helpers.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package helpers
  2. import (
  3. "encoding/json"
  4. "strings"
  5. "time"
  6. "github.com/gomarkdown/markdown"
  7. "github.com/gomarkdown/markdown/html"
  8. "github.com/gomarkdown/markdown/parser"
  9. "github.com/redis/go-redis/v9"
  10. )
  11. const HEADER_KEY = "header-links"
  12. const MENU_KEY = "menu-config"
  13. const ADMIN_TABLE_KEY = "admin-tables"
  14. const TECHNICAL = "technical"
  15. const CONFIGURATION = "configuration"
  16. const BLOG = "blog"
  17. const CREATIVE = "creative"
  18. const DIGITAL_ART = "digital_art"
  19. var Topics = []string{
  20. TECHNICAL,
  21. BLOG,
  22. CREATIVE,
  23. }
  24. var TopicMap = map[string]string{
  25. TECHNICAL: TECHNICAL,
  26. BLOG: BLOG,
  27. CREATIVE: CREATIVE,
  28. }
  29. type HeaderCollection struct {
  30. Category string `json:"category"`
  31. Elements []HeaderElem `json:"elements"`
  32. }
  33. type HeaderElem struct {
  34. Png string `json:"png"`
  35. Link string `json:"link"`
  36. }
  37. type ImageElement struct {
  38. ImgUrl string `json:"img_url"`
  39. }
  40. type MenuElement struct {
  41. Png string `json:"png"`
  42. Category string `json:"category"`
  43. MenuLinks []MenuLinkPair `json:"menu_links"`
  44. }
  45. type MenuLinkPair struct {
  46. MenuLink string `json:"menu_link"`
  47. LinkText string `json:"link_text"`
  48. }
  49. type Document struct {
  50. Ident string `json:"identifier"`
  51. Created string `json:"created"`
  52. Body string `json:"body"`
  53. Category string `json:"category"`
  54. Sample string
  55. }
  56. type AdminTables struct {
  57. Tables []Table `json:"tables"`
  58. }
  59. type Table struct {
  60. TableName string `json:"table_name"`
  61. TableData []TableData `json:"table_data"`
  62. }
  63. type TableData struct {
  64. DisplayName string `json:"display_name"`
  65. Link string `json:"link"`
  66. }
  67. func NewDocument(ident string, created *time.Time, body string, category string) Document {
  68. var ts time.Time
  69. if created == nil {
  70. rn := time.Now()
  71. ts = time.Date(rn.Year(), rn.Month(), rn.Day(), rn.Hour(), rn.Minute(),
  72. rn.Second(), rn.Nanosecond(), rn.Location())
  73. } else {
  74. ts = *created
  75. }
  76. return Document{Ident: ident, Created: ts.String(), Body: body, Category: category}
  77. }
  78. type DocumentUpload struct {
  79. Name string `json:"name"`
  80. Category string `json:"category"`
  81. Text string `json:"text"`
  82. }
  83. type HeaderIo interface {
  84. GetHeaders() (*HeaderCollection, error)
  85. AddHeaders(HeaderCollection) error
  86. GetMenuLinks() (*MenuElement, error)
  87. }
  88. /*
  89. Retrieves the header data from the redis database
  90. */
  91. func GetHeaders(redisCfg RedisConf) (*HeaderCollection, error) {
  92. rds := NewRedisClient(redisCfg)
  93. d, err := rds.Client.Get(rds.ctx, HEADER_KEY).Result()
  94. if err != nil {
  95. if err == redis.Nil {
  96. return nil, nil
  97. }
  98. return nil, err
  99. }
  100. header := &HeaderCollection{}
  101. err = json.Unmarshal([]byte(d), header)
  102. if err != nil {
  103. return nil, err
  104. }
  105. return header, nil
  106. }
  107. /*
  108. Retrieves the menu elements from the database
  109. */
  110. func GetMenuLinks(redisCfg RedisConf) (*MenuElement, error) {
  111. rds := NewRedisClient(redisCfg)
  112. d, err := rds.Client.Get(rds.ctx, MENU_KEY).Result()
  113. if err != nil {
  114. if err == redis.Nil {
  115. return nil, nil
  116. }
  117. return nil, err
  118. }
  119. header := &MenuElement{}
  120. err = json.Unmarshal([]byte(d), header)
  121. if err != nil {
  122. return nil, err
  123. }
  124. return header, nil
  125. }
  126. /*
  127. retreives the admin table config from the database
  128. */
  129. func GetAdminTables(redisCfg RedisConf) (*AdminTables, error) {
  130. rds := NewRedisClient(redisCfg)
  131. d, err := rds.Client.Get(rds.ctx, ADMIN_TABLE_KEY).Result()
  132. if err != nil {
  133. if err == redis.Nil {
  134. return nil, nil
  135. }
  136. return nil, err
  137. }
  138. tables := &AdminTables{}
  139. err = json.Unmarshal([]byte(d), tables)
  140. if err != nil {
  141. return nil, err
  142. }
  143. return tables, nil
  144. }
  145. /*
  146. Place holder func to create the header element in redis
  147. */
  148. func AddHeaders(h HeaderCollection, redisCfg RedisConf) error {
  149. rdc := NewRedisClient(redisCfg)
  150. data, err := json.Marshal(&h)
  151. if err != nil {
  152. return err
  153. }
  154. err = rdc.Client.Set(rdc.ctx, HEADER_KEY, data, 0).Err()
  155. if err != nil {
  156. return err
  157. }
  158. return nil
  159. }
  160. /*
  161. Truncates a text post into a 256 character long 'sample' for displaying posts
  162. */
  163. func (d *Document) MakeSample() string {
  164. t := strings.Split(d.Body, "")
  165. var sample []string
  166. if len(d.Body) < 256 {
  167. return d.Body
  168. }
  169. for i := 0; i < 256; i++ {
  170. sample = append(sample, t[i])
  171. }
  172. sample = append(sample, " ...")
  173. return strings.Join(sample, "")
  174. }
  175. /*
  176. Retrieve all documents from the category specified in the argument category
  177. :param category: the category to get documents from
  178. */
  179. func GetAllDocuments(category string, redisCfg RedisConf) ([]*Document, error) {
  180. rdc := NewRedisClient(redisCfg)
  181. ids, err := rdc.AllDocIds()
  182. if err != nil {
  183. return nil, err
  184. }
  185. var docs []*Document
  186. for idx := range ids {
  187. doc, err := rdc.GetItem(ids[idx])
  188. if err != nil {
  189. return nil, err
  190. }
  191. if doc.Category != category {
  192. continue
  193. }
  194. docs = append(docs, &Document{
  195. Ident: doc.Ident,
  196. Created: doc.Created,
  197. Body: doc.Body,
  198. Sample: doc.MakeSample(),
  199. })
  200. }
  201. return docs, nil
  202. }
  203. /*
  204. adds a text post document to the redis database
  205. */
  206. func AddDocument(d Document, redisCfg RedisConf) error {
  207. rdc := NewRedisClient(redisCfg)
  208. return rdc.AddDoc(d)
  209. }
  210. /*
  211. convert markdown to html
  212. :param md: the byte array containing the Markdown to convert
  213. */
  214. func MdToHTML(md []byte) []byte {
  215. extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock
  216. p := parser.NewWithExtensions(extensions)
  217. doc := p.Parse(md)
  218. htmlFlags := html.CommonFlags | html.HrefTargetBlank
  219. opts := html.RendererOptions{Flags: htmlFlags}
  220. renderer := html.NewRenderer(opts)
  221. return markdown.Render(doc, renderer)
  222. }