diff --git a/activitypub/outbox/outbox.go b/activitypub/outbox/outbox.go index a16017a37..0e0d89a10 100644 --- a/activitypub/outbox/outbox.go +++ b/activitypub/outbox/outbox.go @@ -77,8 +77,8 @@ func SendLive() error { if err == nil { var imageToAttach string var mediaType string - previewGif := filepath.Join(config.WebRoot, "preview.gif") - thumbnailJpg := filepath.Join(config.WebRoot, "thumbnail.jpg") + previewGif := filepath.Join(config.TempDir, "preview.gif") + thumbnailJpg := filepath.Join(config.TempDir, "thumbnail.jpg") uniquenessString := shortid.MustGenerate() if utils.DoesFileExists(previewGif) { imageToAttach = "preview.gif" diff --git a/config/constants.go b/config/constants.go index 5e860bf57..5a5d57f22 100644 --- a/config/constants.go +++ b/config/constants.go @@ -5,8 +5,6 @@ import "path/filepath" const ( // StaticVersionNumber is the version of Owncast that is used when it's not overwritten via build-time settings. StaticVersionNumber = "0.0.12" // Shown when you build from develop - // WebRoot is the web server root directory. - WebRoot = "webroot" // FfmpegSuggestedVersion is the version of ffmpeg we suggest. FfmpegSuggestedVersion = "v4.1.5" // Requires the v // DataDirectory is the directory we save data to. diff --git a/controllers/emoji.go b/controllers/emoji.go index 11f8db7ef..0661b99ce 100644 --- a/controllers/emoji.go +++ b/controllers/emoji.go @@ -2,59 +2,60 @@ package controllers import ( "encoding/json" + "io/fs" "net/http" - "os" - "path" "path/filepath" "strings" - "time" "github.com/owncast/owncast/config" "github.com/owncast/owncast/models" + "github.com/owncast/owncast/static" + "github.com/owncast/owncast/utils" log "github.com/sirupsen/logrus" ) -var ( - emojiCache = make([]models.CustomEmoji, 0) - emojiCacheTimestamp time.Time -) - // getCustomEmojiList returns a list of custom emoji either from the cache or from the emoji directory. func getCustomEmojiList() []models.CustomEmoji { - fullPath := filepath.Join(config.WebRoot, config.EmojiDir) - emojiDirInfo, err := os.Stat(fullPath) + bundledEmoji := static.GetEmoji() + emojiResponse := make([]models.CustomEmoji, 0) + + files, err := fs.Glob(bundledEmoji, "*") if err != nil { log.Errorln(err) - } - if emojiDirInfo.ModTime() != emojiCacheTimestamp { - log.Traceln("Emoji cache invalid") - emojiCache = make([]models.CustomEmoji, 0) + return emojiResponse } - if len(emojiCache) == 0 { - files, err := os.ReadDir(fullPath) - if err != nil { - log.Errorln(err) - return emojiCache - } - for _, f := range files { - name := strings.TrimSuffix(f.Name(), path.Ext(f.Name())) - emojiPath := filepath.Join(config.EmojiDir, f.Name()) - singleEmoji := models.CustomEmoji{Name: name, URL: emojiPath} - emojiCache = append(emojiCache, singleEmoji) - } - - emojiCacheTimestamp = emojiDirInfo.ModTime() + for _, name := range files { + emojiPath := filepath.Join(config.EmojiDir, name) + singleEmoji := models.CustomEmoji{Name: name, URL: emojiPath} + emojiResponse = append(emojiResponse, singleEmoji) } - return emojiCache + return emojiResponse } -// GetCustomEmoji returns a list of custom emoji via the API. -func GetCustomEmoji(w http.ResponseWriter, r *http.Request) { +// GetCustomEmojiList returns a list of custom emoji via the API. +func GetCustomEmojiList(w http.ResponseWriter, r *http.Request) { emojiList := getCustomEmojiList() if err := json.NewEncoder(w).Encode(emojiList); err != nil { InternalErrorHandler(w, err) } } + +// GetCustomEmojiImage returns a single emoji image. +func GetCustomEmojiImage(w http.ResponseWriter, r *http.Request) { + bundledEmoji := static.GetEmoji() + path := strings.TrimPrefix(r.URL.Path, "/img/emoji/") + + b, err := fs.ReadFile(bundledEmoji, path) + if err != nil { + log.Errorln(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + contentType := "image/jpeg" + cacheTime := utils.GetCacheDurationSecondsForPath(path) + writeBytesAsImage(b, contentType, w, cacheTime) +} diff --git a/controllers/images.go b/controllers/images.go new file mode 100644 index 000000000..3fc1e3d63 --- /dev/null +++ b/controllers/images.go @@ -0,0 +1,59 @@ +package controllers + +import ( + "net/http" + "path/filepath" + + "github.com/owncast/owncast/config" + "github.com/owncast/owncast/utils" +) + +// GetThumbnail will return the thumbnail image as a response. +func GetThumbnail(w http.ResponseWriter, r *http.Request) { + imageFilename := "thumbnail.jpg" + imagePath := filepath.Join(config.TempDir, imageFilename) + + var imageBytes []byte + var err error + + if utils.DoesFileExists(imagePath) { + imageBytes, err = getImage(imagePath) + } else { + GetLogo(w, r) + return + } + + if err != nil { + GetLogo(w, r) + return + } + + contentType := "image/jpeg" + cacheTime := utils.GetCacheDurationSecondsForPath(imagePath) + writeBytesAsImage(imageBytes, contentType, w, cacheTime) +} + +// GetPreview will return the preview gif as a response. +func GetPreview(w http.ResponseWriter, r *http.Request) { + imageFilename := "preview.gif" + imagePath := filepath.Join(config.TempDir, imageFilename) + + var imageBytes []byte + var err error + + if utils.DoesFileExists(imagePath) { + imageBytes, err = getImage(imagePath) + } else { + GetLogo(w, r) + return + } + + if err != nil { + GetLogo(w, r) + return + } + + contentType := "image/jpeg" + cacheTime := utils.GetCacheDurationSecondsForPath(imagePath) + writeBytesAsImage(imageBytes, contentType, w, cacheTime) +} diff --git a/controllers/index.go b/controllers/index.go index 20753d2c1..32b16cc56 100644 --- a/controllers/index.go +++ b/controllers/index.go @@ -1,20 +1,11 @@ package controllers import ( - "fmt" "net/http" - "net/url" "path/filepath" - "strings" - log "github.com/sirupsen/logrus" - - "github.com/owncast/owncast/config" - "github.com/owncast/owncast/core" - "github.com/owncast/owncast/core/data" "github.com/owncast/owncast/models" "github.com/owncast/owncast/router/middleware" - "github.com/owncast/owncast/static" "github.com/owncast/owncast/utils" ) @@ -35,10 +26,6 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { middleware.EnableCors(w) isIndexRequest := r.URL.Path == "/" || filepath.Base(r.URL.Path) == "index.html" || filepath.Base(r.URL.Path) == "" - if isIndexRequest { - handleScraperMetadataPage(w, r) - return - } if utils.IsUserAgentAPlayer(r.UserAgent()) && isIndexRequest { http.Redirect(w, r, "/hls/stream.m3u8", http.StatusTemporaryRedirect) @@ -46,10 +33,10 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { } // If the ETags match then return a StatusNotModified - if responseCode := middleware.ProcessEtags(w, r); responseCode != 0 { - w.WriteHeader(responseCode) - return - } + // if responseCode := middleware.ProcessEtags(w, r); responseCode != 0 { + // w.WriteHeader(responseCode) + // return + // } // If this is a directory listing request then return a 404 // info, err := os.Stat(path.Join(config.WebRoot, r.URL.Path)) @@ -65,67 +52,4 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { middleware.SetHeaders(w) serveWeb(w, r) - - // http.ServeFile(w, r, path.Join(config.WebRoot, r.URL.Path)) -} - -// Return a basic HTML page with server-rendered metadata from the config -// to give to Opengraph clients and web scrapers (bots, web crawlers, etc). -func handleScraperMetadataPage(w http.ResponseWriter, r *http.Request) { - tmpl, err := static.GetWebIndexTemplate() - if err != nil { - log.Errorln(err) - w.WriteHeader(http.StatusInternalServerError) - return - } - - scheme := "http" - - if siteURL := data.GetServerURL(); siteURL != "" { - if parsed, err := url.Parse(siteURL); err == nil && parsed.Scheme != "" { - scheme = parsed.Scheme - } - } - - fullURL, err := url.Parse(fmt.Sprintf("%s://%s%s", scheme, r.Host, r.URL.Path)) - if err != nil { - log.Errorln(err) - } - imageURL, err := url.Parse(fmt.Sprintf("%s://%s%s", scheme, r.Host, "/logo/external")) - if err != nil { - log.Errorln(err) - } - - status := core.GetStatus() - - // If the thumbnail does not exist or we're offline then just use the logo image - var thumbnailURL string - if status.Online && utils.DoesFileExists(filepath.Join(config.WebRoot, "thumbnail.jpg")) { - thumbnail, err := url.Parse(fmt.Sprintf("%s://%s%s", scheme, r.Host, "/thumbnail.jpg")) - if err != nil { - log.Errorln(err) - thumbnailURL = imageURL.String() - } else { - thumbnailURL = thumbnail.String() - } - } else { - thumbnailURL = imageURL.String() - } - - tagsString := strings.Join(data.GetServerMetadataTags(), ",") - metadata := MetadataPage{ - Name: data.GetServerName(), - RequestedURL: fullURL.String(), - Image: imageURL.String(), - Summary: data.GetServerSummary(), - Thumbnail: thumbnailURL, - TagsString: tagsString, - Tags: data.GetServerMetadataTags(), - SocialHandles: data.GetSocialHandles(), - } - - w.Header().Set("Content-Type", "text/html") - if err := tmpl.Execute(w, metadata); err != nil { - log.Errorln(err) - } } diff --git a/controllers/logo.go b/controllers/logo.go index 580a0cb5b..2bcda25b1 100644 --- a/controllers/logo.go +++ b/controllers/logo.go @@ -8,6 +8,7 @@ import ( "github.com/owncast/owncast/config" "github.com/owncast/owncast/core/data" + "github.com/owncast/owncast/static" "github.com/owncast/owncast/utils" log "github.com/sirupsen/logrus" ) @@ -21,7 +22,7 @@ func GetLogo(w http.ResponseWriter, r *http.Request) { returnDefault(w) return } - imagePath := filepath.Join("data", imageFilename) + imagePath := filepath.Join(config.DataDirectory, imageFilename) imageBytes, err := getImage(imagePath) if err != nil { returnDefault(w) @@ -56,7 +57,7 @@ func GetCompatibleLogo(w http.ResponseWriter, r *http.Request) { } // Otherwise use a fallback logo.png. - imagePath := filepath.Join(config.WebRoot, "img", "logo.png") + imagePath := filepath.Join(config.DataDirectory, "logo.png") contentType := "image/png" imageBytes, err := getImage(imagePath) if err != nil { @@ -74,14 +75,9 @@ func GetCompatibleLogo(w http.ResponseWriter, r *http.Request) { } func returnDefault(w http.ResponseWriter) { - imagePath := filepath.Join(config.WebRoot, "img", "logo.svg") - imageBytes, err := getImage(imagePath) - if err != nil { - log.Errorln(err) - return - } - cacheTime := utils.GetCacheDurationSecondsForPath(imagePath) - writeBytesAsImage(imageBytes, "image/svg+xml", w, cacheTime) + imageBytes := static.GetLogo() + cacheTime := utils.GetCacheDurationSecondsForPath("logo.png") + writeBytesAsImage(imageBytes, "image/png", w, cacheTime) } func writeBytesAsImage(data []byte, contentType string, w http.ResponseWriter, cacheSeconds int) { diff --git a/controllers/web.go b/controllers/web.go index 579716992..1bef2cd24 100644 --- a/controllers/web.go +++ b/controllers/web.go @@ -16,13 +16,13 @@ import ( // serveWeb will serve web assets. func serveWeb(w http.ResponseWriter, r *http.Request) { // If the ETags match then return a StatusNotModified - if responseCode := middleware.ProcessEtags(w, r); responseCode != 0 { - w.WriteHeader(responseCode) - return - } + // if responseCode := middleware.ProcessEtags(w, r); responseCode != 0 { + // w.WriteHeader(responseCode) + // return + // } webFiles := static.GetWeb() - path := "web/" + strings.TrimPrefix(r.URL.Path, "/") + path := strings.TrimPrefix(r.URL.Path, "/") // Determine if the requested path is a directory. // If so, append index.html to the request. @@ -48,7 +48,7 @@ func serveWeb(w http.ResponseWriter, r *http.Request) { // Set a cache control max-age header middleware.SetCachingHeaders(w, r) - d, err := webFiles.ReadFile(path) + d, err := fs.ReadFile(webFiles, path) if err != nil { log.Errorln(err) w.WriteHeader(http.StatusInternalServerError) diff --git a/core/core.go b/core/core.go index 576a9121d..aefcd3a20 100644 --- a/core/core.go +++ b/core/core.go @@ -112,12 +112,13 @@ func transitionToOfflineVideoStreamContent() { // Copy the logo to be the thumbnail logo := data.GetLogoPath() - if err = utils.Copy(filepath.Join("data", logo), "webroot/thumbnail.jpg"); err != nil { + dst := filepath.Join(config.TempDir, "thumbnail.jpg") + if err = utils.Copy(filepath.Join("data", logo), dst); err != nil { log.Warnln(err) } // Delete the preview Gif - _ = os.Remove(path.Join(config.WebRoot, "preview.gif")) + _ = os.Remove(path.Join(config.DataDirectory, "preview.gif")) } func resetDirectories() { @@ -129,7 +130,7 @@ func resetDirectories() { // Remove the previous thumbnail logo := data.GetLogoPath() if utils.DoesFileExists(logo) { - err := utils.Copy(path.Join("data", logo), filepath.Join(config.WebRoot, "thumbnail.jpg")) + err := utils.Copy(path.Join("data", logo), filepath.Join(config.DataDirectory, "thumbnail.jpg")) if err != nil { log.Warnln(err) } diff --git a/core/data/config.go b/core/data/config.go index c421e5cf6..026669981 100644 --- a/core/data/config.go +++ b/core/data/config.go @@ -2,6 +2,7 @@ package data import ( "errors" + "os" "path/filepath" "sort" "strings" @@ -9,6 +10,7 @@ import ( "github.com/owncast/owncast/config" "github.com/owncast/owncast/models" + "github.com/owncast/owncast/static" "github.com/owncast/owncast/utils" log "github.com/sirupsen/logrus" ) @@ -583,12 +585,10 @@ func VerifySettings() error { logoPath := GetLogoPath() if !utils.DoesFileExists(filepath.Join(config.DataDirectory, logoPath)) { - defaultLogo := filepath.Join(config.WebRoot, "img/logo.svg") log.Traceln(logoPath, "not found in the data directory. copying a default logo.") - if err := utils.Copy(defaultLogo, filepath.Join(config.DataDirectory, "logo.svg")); err != nil { - log.Errorln("error copying default logo: ", err) - } - if err := SetLogoPath("logo.svg"); err != nil { + logo := static.GetLogo() + os.WriteFile(filepath.Join(config.DataDirectory, "logo.png"), logo, 0o600) + if err := SetLogoPath("logo.png"); err != nil { log.Errorln("unable to set default logo to logo.svg", err) } } diff --git a/core/transcoder/thumbnailGenerator.go b/core/transcoder/thumbnailGenerator.go index 102688005..bfc188ad9 100644 --- a/core/transcoder/thumbnailGenerator.go +++ b/core/transcoder/thumbnailGenerator.go @@ -49,8 +49,8 @@ func StartThumbnailGenerator(chunkPath string, variantIndex int) { func fireThumbnailGenerator(segmentPath string, variantIndex int) error { // JPG takes less time to encode than PNG - outputFile := path.Join(config.WebRoot, "thumbnail.jpg") - previewGifFile := path.Join(config.WebRoot, "preview.gif") + outputFile := path.Join(config.TempDir, "thumbnail.jpg") + previewGifFile := path.Join(config.TempDir, "preview.gif") framePath := path.Join(segmentPath, strconv.Itoa(variantIndex)) files, err := os.ReadDir(framePath) @@ -87,7 +87,7 @@ func fireThumbnailGenerator(segmentPath string, variantIndex int) error { mostRecentFile := path.Join(framePath, names[0]) ffmpegPath := utils.ValidatedFfmpegPath(data.GetFfMpegPath()) - outputFileTemp := path.Join(config.WebRoot, "tempthumbnail.jpg") + outputFileTemp := path.Join(config.TempDir, "tempthumbnail.jpg") thumbnailCmdFlags := []string{ ffmpegPath, @@ -117,7 +117,7 @@ func fireThumbnailGenerator(segmentPath string, variantIndex int) error { func makeAnimatedGifPreview(sourceFile string, outputFile string) { ffmpegPath := utils.ValidatedFfmpegPath(data.GetFfMpegPath()) - outputFileTemp := path.Join(config.WebRoot, "temppreview.gif") + outputFileTemp := path.Join(config.TempDir, "temppreview.gif") // Filter is pulled from https://engineering.giphy.com/how-to-make-gifs-with-ffmpeg/ animatedGifFlags := []string{ diff --git a/router/middleware/caching.go b/router/middleware/caching.go index 4c6199554..a3e46e0f6 100644 --- a/router/middleware/caching.go +++ b/router/middleware/caching.go @@ -2,12 +2,8 @@ package middleware import ( "net/http" - "os" - "path/filepath" "strconv" - "github.com/amalfra/etag" - "github.com/owncast/owncast/config" "github.com/owncast/owncast/utils" ) @@ -22,25 +18,6 @@ func setCacheSeconds(seconds int, w http.ResponseWriter) { w.Header().Set("Cache-Control", "public, max-age="+secondsStr) } -// ProcessEtags gets and sets ETags for caching purposes. -func ProcessEtags(w http.ResponseWriter, r *http.Request) int { - info, err := os.Stat(filepath.Join(config.WebRoot, r.URL.Path)) - if err != nil { - return 0 - } - - localContentEtag := etag.Generate(info.ModTime().String(), true) - if remoteEtagHeader := r.Header.Get("If-None-Match"); remoteEtagHeader != "" { - if remoteEtagHeader == localContentEtag { - return http.StatusNotModified - } - } - - w.Header().Set("Etag", localContentEtag) - - return 0 -} - // SetCachingHeaders will set the cache control header of a response. func SetCachingHeaders(w http.ResponseWriter, r *http.Request) { setCacheSeconds(utils.GetCacheDurationSecondsForPath(r.URL.Path), w) diff --git a/router/router.go b/router/router.go index 0344b7885..f697c4ee9 100644 --- a/router/router.go +++ b/router/router.go @@ -25,15 +25,26 @@ import ( // Start starts the router for the http, ws, and rtmp. func Start() error { - // static files + // The admin web app. http.HandleFunc("/admin", middleware.RequireAdminAuth(controllers.IndexHandler)) + + // The primary web app. http.HandleFunc("/", controllers.IndexHandler) + // Return a single emoji image. + http.HandleFunc("/img/emoji/", middleware.RequireAdminAuth(controllers.GetCustomEmojiImage)) + + // return the logo + http.HandleFunc("/logo", controllers.GetLogo) + + // return a logo that's compatible with external social networks + http.HandleFunc("/logo/external", controllers.GetCompatibleLogo) + // status of the system http.HandleFunc("/api/status", controllers.GetStatus) // custom emoji supported in the chat - http.HandleFunc("/api/emoji", controllers.GetCustomEmoji) + http.HandleFunc("/api/emoji", controllers.GetCustomEmojiList) // chat rest api http.HandleFunc("/api/chat", middleware.RequireUserAccessToken(controllers.GetChatMessages)) @@ -59,12 +70,6 @@ func Start() error { // list of all social platforms http.HandleFunc("/api/socialplatforms", controllers.GetAllSocialPlatforms) - // return the logo - http.HandleFunc("/logo", controllers.GetLogo) - - // return a logo that's compatible with external social networks - http.HandleFunc("/logo/external", controllers.GetCompatibleLogo) - // return the list of video variants available http.HandleFunc("/api/video/variants", controllers.GetVideoStreamOutputVariants) diff --git a/static/img/emoji/Reaper-gg.png b/static/img/emoji/Reaper-gg.png new file mode 100644 index 000000000..de6d571e6 Binary files /dev/null and b/static/img/emoji/Reaper-gg.png differ diff --git a/static/img/emoji/Reaper-hi.png b/static/img/emoji/Reaper-hi.png new file mode 100644 index 000000000..dc6b6aedc Binary files /dev/null and b/static/img/emoji/Reaper-hi.png differ diff --git a/static/img/emoji/Reaper-hype.png b/static/img/emoji/Reaper-hype.png new file mode 100644 index 000000000..2138dba90 Binary files /dev/null and b/static/img/emoji/Reaper-hype.png differ diff --git a/static/img/emoji/Reaper-lol.png b/static/img/emoji/Reaper-lol.png new file mode 100644 index 000000000..8c4eff264 Binary files /dev/null and b/static/img/emoji/Reaper-lol.png differ diff --git a/static/img/emoji/Reaper-love.png b/static/img/emoji/Reaper-love.png new file mode 100644 index 000000000..5e0f3ba7b Binary files /dev/null and b/static/img/emoji/Reaper-love.png differ diff --git a/static/img/emoji/Reaper-rage.png b/static/img/emoji/Reaper-rage.png new file mode 100644 index 000000000..3da0a5d83 Binary files /dev/null and b/static/img/emoji/Reaper-rage.png differ diff --git a/static/img/emoji/Reaper-rip.png b/static/img/emoji/Reaper-rip.png new file mode 100644 index 000000000..89c13c789 Binary files /dev/null and b/static/img/emoji/Reaper-rip.png differ diff --git a/static/img/emoji/Reaper-wtf.png b/static/img/emoji/Reaper-wtf.png new file mode 100644 index 000000000..e21adb6a2 Binary files /dev/null and b/static/img/emoji/Reaper-wtf.png differ diff --git a/static/img/emoji/ac-box.png b/static/img/emoji/ac-box.png new file mode 100644 index 000000000..18bd9b35d Binary files /dev/null and b/static/img/emoji/ac-box.png differ diff --git a/static/img/emoji/ac-construction.png b/static/img/emoji/ac-construction.png new file mode 100644 index 000000000..ee2b6f3c3 Binary files /dev/null and b/static/img/emoji/ac-construction.png differ diff --git a/static/img/emoji/ac-fossil.png b/static/img/emoji/ac-fossil.png new file mode 100644 index 000000000..16d4fad73 Binary files /dev/null and b/static/img/emoji/ac-fossil.png differ diff --git a/static/img/emoji/ac-item-leaf.png b/static/img/emoji/ac-item-leaf.png new file mode 100644 index 000000000..6abede7b1 Binary files /dev/null and b/static/img/emoji/ac-item-leaf.png differ diff --git a/static/img/emoji/ac-kkslider.png b/static/img/emoji/ac-kkslider.png new file mode 100644 index 000000000..309d768f5 Binary files /dev/null and b/static/img/emoji/ac-kkslider.png differ diff --git a/static/img/emoji/ac-moneytree.png b/static/img/emoji/ac-moneytree.png new file mode 100644 index 000000000..3e370acd4 Binary files /dev/null and b/static/img/emoji/ac-moneytree.png differ diff --git a/static/img/emoji/ac-mosquito.png b/static/img/emoji/ac-mosquito.png new file mode 100644 index 000000000..50ddb4110 Binary files /dev/null and b/static/img/emoji/ac-mosquito.png differ diff --git a/static/img/emoji/ac-shirt.png b/static/img/emoji/ac-shirt.png new file mode 100644 index 000000000..41ab1d8de Binary files /dev/null and b/static/img/emoji/ac-shirt.png differ diff --git a/static/img/emoji/ac-song.png b/static/img/emoji/ac-song.png new file mode 100644 index 000000000..dfe9d847c Binary files /dev/null and b/static/img/emoji/ac-song.png differ diff --git a/static/img/emoji/ac-tree.png b/static/img/emoji/ac-tree.png new file mode 100644 index 000000000..499ee4ec4 Binary files /dev/null and b/static/img/emoji/ac-tree.png differ diff --git a/static/img/emoji/ac-turnip.png b/static/img/emoji/ac-turnip.png new file mode 100644 index 000000000..893ef9cff Binary files /dev/null and b/static/img/emoji/ac-turnip.png differ diff --git a/static/img/emoji/ac-weeds.png b/static/img/emoji/ac-weeds.png new file mode 100644 index 000000000..6d3b23716 Binary files /dev/null and b/static/img/emoji/ac-weeds.png differ diff --git a/static/img/emoji/alert.gif b/static/img/emoji/alert.gif new file mode 100644 index 000000000..43b4b981e Binary files /dev/null and b/static/img/emoji/alert.gif differ diff --git a/static/img/emoji/bananadance.gif b/static/img/emoji/bananadance.gif new file mode 100644 index 000000000..da6f470bc Binary files /dev/null and b/static/img/emoji/bananadance.gif differ diff --git a/static/img/emoji/bb8.png b/static/img/emoji/bb8.png new file mode 100644 index 000000000..e97e3f3d5 Binary files /dev/null and b/static/img/emoji/bb8.png differ diff --git a/static/img/emoji/beerparrot.gif b/static/img/emoji/beerparrot.gif new file mode 100644 index 000000000..2cd83ee15 Binary files /dev/null and b/static/img/emoji/beerparrot.gif differ diff --git a/static/img/emoji/bells.png b/static/img/emoji/bells.png new file mode 100644 index 000000000..1a20ab040 Binary files /dev/null and b/static/img/emoji/bells.png differ diff --git a/static/img/emoji/birthdaypartyparrot.gif b/static/img/emoji/birthdaypartyparrot.gif new file mode 100644 index 000000000..4c166eabb Binary files /dev/null and b/static/img/emoji/birthdaypartyparrot.gif differ diff --git a/static/img/emoji/blacklightsaber.png b/static/img/emoji/blacklightsaber.png new file mode 100644 index 000000000..1a537968a Binary files /dev/null and b/static/img/emoji/blacklightsaber.png differ diff --git a/static/img/emoji/bluelightsaber.png b/static/img/emoji/bluelightsaber.png new file mode 100644 index 000000000..b509c73ea Binary files /dev/null and b/static/img/emoji/bluelightsaber.png differ diff --git a/static/img/emoji/bluntparrot.gif b/static/img/emoji/bluntparrot.gif new file mode 100644 index 000000000..6d33f7d38 Binary files /dev/null and b/static/img/emoji/bluntparrot.gif differ diff --git a/static/img/emoji/bobaparrot.gif b/static/img/emoji/bobaparrot.gif new file mode 100644 index 000000000..17ecdfad9 Binary files /dev/null and b/static/img/emoji/bobaparrot.gif differ diff --git a/static/img/emoji/cakeparrot.gif b/static/img/emoji/cakeparrot.gif new file mode 100644 index 000000000..8ddb47f04 Binary files /dev/null and b/static/img/emoji/cakeparrot.gif differ diff --git a/static/img/emoji/chewbacca.png b/static/img/emoji/chewbacca.png new file mode 100644 index 000000000..4cae67bbe Binary files /dev/null and b/static/img/emoji/chewbacca.png differ diff --git a/static/img/emoji/chillparrot.gif b/static/img/emoji/chillparrot.gif new file mode 100644 index 000000000..0d7a560e1 Binary files /dev/null and b/static/img/emoji/chillparrot.gif differ diff --git a/static/img/emoji/christmasparrot.gif b/static/img/emoji/christmasparrot.gif new file mode 100644 index 000000000..417c3e074 Binary files /dev/null and b/static/img/emoji/christmasparrot.gif differ diff --git a/static/img/emoji/coffeeparrot.gif b/static/img/emoji/coffeeparrot.gif new file mode 100644 index 000000000..3a935d229 Binary files /dev/null and b/static/img/emoji/coffeeparrot.gif differ diff --git a/static/img/emoji/confusedparrot.gif b/static/img/emoji/confusedparrot.gif new file mode 100644 index 000000000..e641f4393 Binary files /dev/null and b/static/img/emoji/confusedparrot.gif differ diff --git a/static/img/emoji/copparrot.gif b/static/img/emoji/copparrot.gif new file mode 100644 index 000000000..b41a4744d Binary files /dev/null and b/static/img/emoji/copparrot.gif differ diff --git a/static/img/emoji/coronavirus.png b/static/img/emoji/coronavirus.png new file mode 100644 index 000000000..6c6566485 Binary files /dev/null and b/static/img/emoji/coronavirus.png differ diff --git a/static/img/emoji/covid19parrot.gif b/static/img/emoji/covid19parrot.gif new file mode 100644 index 000000000..70beb621b Binary files /dev/null and b/static/img/emoji/covid19parrot.gif differ diff --git a/static/img/emoji/cryptoparrot.gif b/static/img/emoji/cryptoparrot.gif new file mode 100644 index 000000000..acd98d0db Binary files /dev/null and b/static/img/emoji/cryptoparrot.gif differ diff --git a/static/img/emoji/dabparrot.gif b/static/img/emoji/dabparrot.gif new file mode 100644 index 000000000..5f95dd4a2 Binary files /dev/null and b/static/img/emoji/dabparrot.gif differ diff --git a/static/img/emoji/dadparrot.gif b/static/img/emoji/dadparrot.gif new file mode 100644 index 000000000..5e025ddc5 Binary files /dev/null and b/static/img/emoji/dadparrot.gif differ diff --git a/static/img/emoji/daftpunkparrot.gif b/static/img/emoji/daftpunkparrot.gif new file mode 100644 index 000000000..be7a1cf31 Binary files /dev/null and b/static/img/emoji/daftpunkparrot.gif differ diff --git a/static/img/emoji/darkbeerparrot.gif b/static/img/emoji/darkbeerparrot.gif new file mode 100644 index 000000000..c37edb504 Binary files /dev/null and b/static/img/emoji/darkbeerparrot.gif differ diff --git a/static/img/emoji/darkmodeparrot.gif b/static/img/emoji/darkmodeparrot.gif new file mode 100644 index 000000000..b9ed2051d Binary files /dev/null and b/static/img/emoji/darkmodeparrot.gif differ diff --git a/static/img/emoji/darth_vader.png b/static/img/emoji/darth_vader.png new file mode 100644 index 000000000..44f43d03d Binary files /dev/null and b/static/img/emoji/darth_vader.png differ diff --git a/static/img/emoji/dealwithitparrot.gif b/static/img/emoji/dealwithitparrot.gif new file mode 100644 index 000000000..f501e5ea5 Binary files /dev/null and b/static/img/emoji/dealwithitparrot.gif differ diff --git a/static/img/emoji/death_star.png b/static/img/emoji/death_star.png new file mode 100644 index 000000000..003a28a56 Binary files /dev/null and b/static/img/emoji/death_star.png differ diff --git a/static/img/emoji/discoparrot.gif b/static/img/emoji/discoparrot.gif new file mode 100644 index 000000000..47a754842 Binary files /dev/null and b/static/img/emoji/discoparrot.gif differ diff --git a/static/img/emoji/division-gg.png b/static/img/emoji/division-gg.png new file mode 100644 index 000000000..d704b46d4 Binary files /dev/null and b/static/img/emoji/division-gg.png differ diff --git a/static/img/emoji/division-hi.png b/static/img/emoji/division-hi.png new file mode 100644 index 000000000..437b36850 Binary files /dev/null and b/static/img/emoji/division-hi.png differ diff --git a/static/img/emoji/division-hype.png b/static/img/emoji/division-hype.png new file mode 100644 index 000000000..b6260bc95 Binary files /dev/null and b/static/img/emoji/division-hype.png differ diff --git a/static/img/emoji/division-lol.png b/static/img/emoji/division-lol.png new file mode 100644 index 000000000..d085493f4 Binary files /dev/null and b/static/img/emoji/division-lol.png differ diff --git a/static/img/emoji/division-omg.png b/static/img/emoji/division-omg.png new file mode 100644 index 000000000..b1100cfc9 Binary files /dev/null and b/static/img/emoji/division-omg.png differ diff --git a/static/img/emoji/division-rage.png b/static/img/emoji/division-rage.png new file mode 100644 index 000000000..55d13a3e7 Binary files /dev/null and b/static/img/emoji/division-rage.png differ diff --git a/static/img/emoji/division-rip.png b/static/img/emoji/division-rip.png new file mode 100644 index 000000000..f57c78b4a Binary files /dev/null and b/static/img/emoji/division-rip.png differ diff --git a/static/img/emoji/division-wtf.png b/static/img/emoji/division-wtf.png new file mode 100644 index 000000000..654cde903 Binary files /dev/null and b/static/img/emoji/division-wtf.png differ diff --git a/static/img/emoji/docparrot.gif b/static/img/emoji/docparrot.gif new file mode 100644 index 000000000..2fb502de5 Binary files /dev/null and b/static/img/emoji/docparrot.gif differ diff --git a/static/img/emoji/donutparrot.gif b/static/img/emoji/donutparrot.gif new file mode 100644 index 000000000..9137e9066 Binary files /dev/null and b/static/img/emoji/donutparrot.gif differ diff --git a/static/img/emoji/doom_mad.gif b/static/img/emoji/doom_mad.gif new file mode 100644 index 000000000..1f124b810 Binary files /dev/null and b/static/img/emoji/doom_mad.gif differ diff --git a/static/img/emoji/empire.png b/static/img/emoji/empire.png new file mode 100644 index 000000000..da2fb8c95 Binary files /dev/null and b/static/img/emoji/empire.png differ diff --git a/static/img/emoji/everythingsfineparrot.gif b/static/img/emoji/everythingsfineparrot.gif new file mode 100644 index 000000000..5680c322e Binary files /dev/null and b/static/img/emoji/everythingsfineparrot.gif differ diff --git a/static/img/emoji/evilparrot.gif b/static/img/emoji/evilparrot.gif new file mode 100644 index 000000000..edb93c02d Binary files /dev/null and b/static/img/emoji/evilparrot.gif differ diff --git a/static/img/emoji/explodyparrot.gif b/static/img/emoji/explodyparrot.gif new file mode 100644 index 000000000..387005d36 Binary files /dev/null and b/static/img/emoji/explodyparrot.gif differ diff --git a/static/img/emoji/fixparrot.gif b/static/img/emoji/fixparrot.gif new file mode 100644 index 000000000..655d423a8 Binary files /dev/null and b/static/img/emoji/fixparrot.gif differ diff --git a/static/img/emoji/flyingmoneyparrot.gif b/static/img/emoji/flyingmoneyparrot.gif new file mode 100644 index 000000000..abf389dd5 Binary files /dev/null and b/static/img/emoji/flyingmoneyparrot.gif differ diff --git a/static/img/emoji/footballparrot.gif b/static/img/emoji/footballparrot.gif new file mode 100644 index 000000000..49472b74a Binary files /dev/null and b/static/img/emoji/footballparrot.gif differ diff --git a/static/img/emoji/gabe1.png b/static/img/emoji/gabe1.png new file mode 100644 index 000000000..89b8c4e5e Binary files /dev/null and b/static/img/emoji/gabe1.png differ diff --git a/static/img/emoji/gabe2.png b/static/img/emoji/gabe2.png new file mode 100644 index 000000000..987d91cf3 Binary files /dev/null and b/static/img/emoji/gabe2.png differ diff --git a/static/img/emoji/gentlemanparrot.gif b/static/img/emoji/gentlemanparrot.gif new file mode 100644 index 000000000..8e8f05bb7 Binary files /dev/null and b/static/img/emoji/gentlemanparrot.gif differ diff --git a/static/img/emoji/githubparrot.gif b/static/img/emoji/githubparrot.gif new file mode 100644 index 000000000..1d7bd14ad Binary files /dev/null and b/static/img/emoji/githubparrot.gif differ diff --git a/static/img/emoji/goomba.gif b/static/img/emoji/goomba.gif new file mode 100644 index 000000000..c6bb719e7 Binary files /dev/null and b/static/img/emoji/goomba.gif differ diff --git a/static/img/emoji/gothparrot.gif b/static/img/emoji/gothparrot.gif new file mode 100644 index 000000000..361b68ecf Binary files /dev/null and b/static/img/emoji/gothparrot.gif differ diff --git a/static/img/emoji/hamburgerparrot.gif b/static/img/emoji/hamburgerparrot.gif new file mode 100644 index 000000000..192b0ff17 Binary files /dev/null and b/static/img/emoji/hamburgerparrot.gif differ diff --git a/static/img/emoji/harrypotterparrot.gif b/static/img/emoji/harrypotterparrot.gif new file mode 100644 index 000000000..032a37e91 Binary files /dev/null and b/static/img/emoji/harrypotterparrot.gif differ diff --git a/static/img/emoji/headbangingparrot.gif b/static/img/emoji/headbangingparrot.gif new file mode 100644 index 000000000..9aad2ecb6 Binary files /dev/null and b/static/img/emoji/headbangingparrot.gif differ diff --git a/static/img/emoji/headingparrot.gif b/static/img/emoji/headingparrot.gif new file mode 100644 index 000000000..b17002c55 Binary files /dev/null and b/static/img/emoji/headingparrot.gif differ diff --git a/static/img/emoji/headsetparrot.gif b/static/img/emoji/headsetparrot.gif new file mode 100644 index 000000000..516a04f1f Binary files /dev/null and b/static/img/emoji/headsetparrot.gif differ diff --git a/static/img/emoji/hmmparrot.gif b/static/img/emoji/hmmparrot.gif new file mode 100644 index 000000000..223a6c251 Binary files /dev/null and b/static/img/emoji/hmmparrot.gif differ diff --git a/static/img/emoji/hypnoparrot.gif b/static/img/emoji/hypnoparrot.gif new file mode 100644 index 000000000..a6a0983d0 Binary files /dev/null and b/static/img/emoji/hypnoparrot.gif differ diff --git a/static/img/emoji/icecreamparrot.gif b/static/img/emoji/icecreamparrot.gif new file mode 100644 index 000000000..0a5093fd0 Binary files /dev/null and b/static/img/emoji/icecreamparrot.gif differ diff --git a/static/img/emoji/illuminatiparrot.gif b/static/img/emoji/illuminatiparrot.gif new file mode 100644 index 000000000..a0c4e7981 Binary files /dev/null and b/static/img/emoji/illuminatiparrot.gif differ diff --git a/static/img/emoji/jediparrot.gif b/static/img/emoji/jediparrot.gif new file mode 100644 index 000000000..410ca698b Binary files /dev/null and b/static/img/emoji/jediparrot.gif differ diff --git a/static/img/emoji/keanu_thanks.gif b/static/img/emoji/keanu_thanks.gif new file mode 100644 index 000000000..989b9b759 Binary files /dev/null and b/static/img/emoji/keanu_thanks.gif differ diff --git a/static/img/emoji/laptop_parrot.gif b/static/img/emoji/laptop_parrot.gif new file mode 100644 index 000000000..b14bb1846 Binary files /dev/null and b/static/img/emoji/laptop_parrot.gif differ diff --git a/static/img/emoji/loveparrot.gif b/static/img/emoji/loveparrot.gif new file mode 100644 index 000000000..c0d14edca Binary files /dev/null and b/static/img/emoji/loveparrot.gif differ diff --git a/static/img/emoji/mandalorian.png b/static/img/emoji/mandalorian.png new file mode 100644 index 000000000..7db4a3b8e Binary files /dev/null and b/static/img/emoji/mandalorian.png differ diff --git a/static/img/emoji/margaritaparrot.gif b/static/img/emoji/margaritaparrot.gif new file mode 100644 index 000000000..10a8c6a83 Binary files /dev/null and b/static/img/emoji/margaritaparrot.gif differ diff --git a/static/img/emoji/mario.gif b/static/img/emoji/mario.gif new file mode 100644 index 000000000..87f113333 Binary files /dev/null and b/static/img/emoji/mario.gif differ diff --git a/static/img/emoji/matrixparrot.gif b/static/img/emoji/matrixparrot.gif new file mode 100644 index 000000000..7281a8435 Binary files /dev/null and b/static/img/emoji/matrixparrot.gif differ diff --git a/static/img/emoji/meldparrot.gif b/static/img/emoji/meldparrot.gif new file mode 100644 index 000000000..ae4605336 Binary files /dev/null and b/static/img/emoji/meldparrot.gif differ diff --git a/static/img/emoji/metalparrot.gif b/static/img/emoji/metalparrot.gif new file mode 100644 index 000000000..f358b2fff Binary files /dev/null and b/static/img/emoji/metalparrot.gif differ diff --git a/static/img/emoji/michaeljacksonparrot.gif b/static/img/emoji/michaeljacksonparrot.gif new file mode 100644 index 000000000..cfa840500 Binary files /dev/null and b/static/img/emoji/michaeljacksonparrot.gif differ diff --git a/static/img/emoji/moonparrot.gif b/static/img/emoji/moonparrot.gif new file mode 100644 index 000000000..098938ab2 Binary files /dev/null and b/static/img/emoji/moonparrot.gif differ diff --git a/static/img/emoji/moonwalkingparrot.gif b/static/img/emoji/moonwalkingparrot.gif new file mode 100644 index 000000000..873f828f5 Binary files /dev/null and b/static/img/emoji/moonwalkingparrot.gif differ diff --git a/static/img/emoji/mustacheparrot.gif b/static/img/emoji/mustacheparrot.gif new file mode 100644 index 000000000..e71fe28d8 Binary files /dev/null and b/static/img/emoji/mustacheparrot.gif differ diff --git a/static/img/emoji/nicolas_cage_party.gif b/static/img/emoji/nicolas_cage_party.gif new file mode 100644 index 000000000..541431710 Binary files /dev/null and b/static/img/emoji/nicolas_cage_party.gif differ diff --git a/static/img/emoji/nodeparrot.gif b/static/img/emoji/nodeparrot.gif new file mode 100644 index 000000000..6735b0b30 Binary files /dev/null and b/static/img/emoji/nodeparrot.gif differ diff --git a/static/img/emoji/norwegianblueparrot.gif b/static/img/emoji/norwegianblueparrot.gif new file mode 100644 index 000000000..0aa9583ec Binary files /dev/null and b/static/img/emoji/norwegianblueparrot.gif differ diff --git a/static/img/emoji/opensourceparrot.gif b/static/img/emoji/opensourceparrot.gif new file mode 100644 index 000000000..706774342 Binary files /dev/null and b/static/img/emoji/opensourceparrot.gif differ diff --git a/static/img/emoji/originalparrot.gif b/static/img/emoji/originalparrot.gif new file mode 100644 index 000000000..428cc2239 Binary files /dev/null and b/static/img/emoji/originalparrot.gif differ diff --git a/static/img/emoji/owncast.png b/static/img/emoji/owncast.png new file mode 100644 index 000000000..6e7fdc9b3 Binary files /dev/null and b/static/img/emoji/owncast.png differ diff --git a/static/img/emoji/palpatine.png b/static/img/emoji/palpatine.png new file mode 100644 index 000000000..ca10fe673 Binary files /dev/null and b/static/img/emoji/palpatine.png differ diff --git a/static/img/emoji/papalparrot.gif b/static/img/emoji/papalparrot.gif new file mode 100644 index 000000000..16ec6ba25 Binary files /dev/null and b/static/img/emoji/papalparrot.gif differ diff --git a/static/img/emoji/parrot.gif b/static/img/emoji/parrot.gif new file mode 100644 index 000000000..b8c261a01 Binary files /dev/null and b/static/img/emoji/parrot.gif differ diff --git a/static/img/emoji/parrotnotfound.gif b/static/img/emoji/parrotnotfound.gif new file mode 100644 index 000000000..a039df9fc Binary files /dev/null and b/static/img/emoji/parrotnotfound.gif differ diff --git a/static/img/emoji/partyparrot.gif b/static/img/emoji/partyparrot.gif new file mode 100644 index 000000000..b88ecc41f Binary files /dev/null and b/static/img/emoji/partyparrot.gif differ diff --git a/static/img/emoji/phparrot.gif b/static/img/emoji/phparrot.gif new file mode 100644 index 000000000..95e33b4f2 Binary files /dev/null and b/static/img/emoji/phparrot.gif differ diff --git a/static/img/emoji/pirateparrot.gif b/static/img/emoji/pirateparrot.gif new file mode 100644 index 000000000..028848abc Binary files /dev/null and b/static/img/emoji/pirateparrot.gif differ diff --git a/static/img/emoji/pizzaparrot.gif b/static/img/emoji/pizzaparrot.gif new file mode 100644 index 000000000..56d9dfc29 Binary files /dev/null and b/static/img/emoji/pizzaparrot.gif differ diff --git a/static/img/emoji/pokeparrot.gif b/static/img/emoji/pokeparrot.gif new file mode 100644 index 000000000..a9adc861a Binary files /dev/null and b/static/img/emoji/pokeparrot.gif differ diff --git a/static/img/emoji/popcornparrot.gif b/static/img/emoji/popcornparrot.gif new file mode 100644 index 000000000..65b8585af Binary files /dev/null and b/static/img/emoji/popcornparrot.gif differ diff --git a/static/img/emoji/porg.png b/static/img/emoji/porg.png new file mode 100644 index 000000000..68d08bfa1 Binary files /dev/null and b/static/img/emoji/porg.png differ diff --git a/static/img/emoji/portalparrot.gif b/static/img/emoji/portalparrot.gif new file mode 100644 index 000000000..5971fbd2a Binary files /dev/null and b/static/img/emoji/portalparrot.gif differ diff --git a/static/img/emoji/pumpkinparrot.gif b/static/img/emoji/pumpkinparrot.gif new file mode 100644 index 000000000..f453ce26f Binary files /dev/null and b/static/img/emoji/pumpkinparrot.gif differ diff --git a/static/img/emoji/quadparrot.gif b/static/img/emoji/quadparrot.gif new file mode 100644 index 000000000..9f1e3195b Binary files /dev/null and b/static/img/emoji/quadparrot.gif differ diff --git a/static/img/emoji/r2d2.png b/static/img/emoji/r2d2.png new file mode 100644 index 000000000..0a7fa098f Binary files /dev/null and b/static/img/emoji/r2d2.png differ diff --git a/static/img/emoji/redenvelopeparrot.gif b/static/img/emoji/redenvelopeparrot.gif new file mode 100644 index 000000000..b40c76cf6 Binary files /dev/null and b/static/img/emoji/redenvelopeparrot.gif differ diff --git a/static/img/emoji/ripparrot.gif b/static/img/emoji/ripparrot.gif new file mode 100644 index 000000000..164250ecd Binary files /dev/null and b/static/img/emoji/ripparrot.gif differ diff --git a/static/img/emoji/rotatingparrot.gif b/static/img/emoji/rotatingparrot.gif new file mode 100644 index 000000000..1916cd0be Binary files /dev/null and b/static/img/emoji/rotatingparrot.gif differ diff --git a/static/img/emoji/ryangoslingparrot.gif b/static/img/emoji/ryangoslingparrot.gif new file mode 100644 index 000000000..f37d170c4 Binary files /dev/null and b/static/img/emoji/ryangoslingparrot.gif differ diff --git a/static/img/emoji/rythmicalparrot.gif b/static/img/emoji/rythmicalparrot.gif new file mode 100644 index 000000000..db3e52d62 Binary files /dev/null and b/static/img/emoji/rythmicalparrot.gif differ diff --git a/static/img/emoji/sadparrot.gif b/static/img/emoji/sadparrot.gif new file mode 100644 index 000000000..25b500dd0 Binary files /dev/null and b/static/img/emoji/sadparrot.gif differ diff --git a/static/img/emoji/schnitzelparrot.gif b/static/img/emoji/schnitzelparrot.gif new file mode 100644 index 000000000..00d22d7ab Binary files /dev/null and b/static/img/emoji/schnitzelparrot.gif differ diff --git a/static/img/emoji/scienceparrot.gif b/static/img/emoji/scienceparrot.gif new file mode 100644 index 000000000..b5e434250 Binary files /dev/null and b/static/img/emoji/scienceparrot.gif differ diff --git a/static/img/emoji/shipitparrot.gif b/static/img/emoji/shipitparrot.gif new file mode 100644 index 000000000..8d1ed30f7 Binary files /dev/null and b/static/img/emoji/shipitparrot.gif differ diff --git a/static/img/emoji/shufflepartyparrot.gif b/static/img/emoji/shufflepartyparrot.gif new file mode 100644 index 000000000..7e754cbd0 Binary files /dev/null and b/static/img/emoji/shufflepartyparrot.gif differ diff --git a/static/img/emoji/sintparrot.gif b/static/img/emoji/sintparrot.gif new file mode 100644 index 000000000..26f083bba Binary files /dev/null and b/static/img/emoji/sintparrot.gif differ diff --git a/static/img/emoji/sithparrot.gif b/static/img/emoji/sithparrot.gif new file mode 100644 index 000000000..b039e67f3 Binary files /dev/null and b/static/img/emoji/sithparrot.gif differ diff --git a/static/img/emoji/skiparrot.gif b/static/img/emoji/skiparrot.gif new file mode 100644 index 000000000..7cfa3c00c Binary files /dev/null and b/static/img/emoji/skiparrot.gif differ diff --git a/static/img/emoji/sleepingparrot.gif b/static/img/emoji/sleepingparrot.gif new file mode 100644 index 000000000..6f0b6dde4 Binary files /dev/null and b/static/img/emoji/sleepingparrot.gif differ diff --git a/static/img/emoji/sonic.gif b/static/img/emoji/sonic.gif new file mode 100644 index 000000000..e9a9f4bac Binary files /dev/null and b/static/img/emoji/sonic.gif differ diff --git a/static/img/emoji/spyparrot.gif b/static/img/emoji/spyparrot.gif new file mode 100644 index 000000000..031b64e04 Binary files /dev/null and b/static/img/emoji/spyparrot.gif differ diff --git a/static/img/emoji/stalkerparrot.gif b/static/img/emoji/stalkerparrot.gif new file mode 100644 index 000000000..349d6494b Binary files /dev/null and b/static/img/emoji/stalkerparrot.gif differ diff --git a/static/img/emoji/starwars.png b/static/img/emoji/starwars.png new file mode 100644 index 000000000..cef654682 Binary files /dev/null and b/static/img/emoji/starwars.png differ diff --git a/static/img/emoji/stayhomeparrot.gif b/static/img/emoji/stayhomeparrot.gif new file mode 100644 index 000000000..800adafd8 Binary files /dev/null and b/static/img/emoji/stayhomeparrot.gif differ diff --git a/static/img/emoji/storm_trooper.gif b/static/img/emoji/storm_trooper.gif new file mode 100644 index 000000000..0f66de7ad Binary files /dev/null and b/static/img/emoji/storm_trooper.gif differ diff --git a/static/img/emoji/stormtrooper.png b/static/img/emoji/stormtrooper.png new file mode 100644 index 000000000..ae9535864 Binary files /dev/null and b/static/img/emoji/stormtrooper.png differ diff --git a/static/img/emoji/sushiparrot.gif b/static/img/emoji/sushiparrot.gif new file mode 100644 index 000000000..27220188a Binary files /dev/null and b/static/img/emoji/sushiparrot.gif differ diff --git a/static/img/emoji/tacoparrot.gif b/static/img/emoji/tacoparrot.gif new file mode 100644 index 000000000..aed1d15d6 Binary files /dev/null and b/static/img/emoji/tacoparrot.gif differ diff --git a/static/img/emoji/tennisparrot.gif b/static/img/emoji/tennisparrot.gif new file mode 100644 index 000000000..97efeddd1 Binary files /dev/null and b/static/img/emoji/tennisparrot.gif differ diff --git a/static/img/emoji/thanks.png b/static/img/emoji/thanks.png new file mode 100644 index 000000000..80e0d32cb Binary files /dev/null and b/static/img/emoji/thanks.png differ diff --git a/static/img/emoji/thumbsupparrot.gif b/static/img/emoji/thumbsupparrot.gif new file mode 100644 index 000000000..df3792194 Binary files /dev/null and b/static/img/emoji/thumbsupparrot.gif differ diff --git a/static/img/emoji/tiedyeparrot.gif b/static/img/emoji/tiedyeparrot.gif new file mode 100644 index 000000000..b9a138efa Binary files /dev/null and b/static/img/emoji/tiedyeparrot.gif differ diff --git a/static/img/emoji/tpparrot.gif b/static/img/emoji/tpparrot.gif new file mode 100644 index 000000000..a64738427 Binary files /dev/null and b/static/img/emoji/tpparrot.gif differ diff --git a/static/img/emoji/transparront.gif b/static/img/emoji/transparront.gif new file mode 100644 index 000000000..f9ecf8b37 Binary files /dev/null and b/static/img/emoji/transparront.gif differ diff --git a/static/img/emoji/twinsparrot.gif b/static/img/emoji/twinsparrot.gif new file mode 100644 index 000000000..c503979df Binary files /dev/null and b/static/img/emoji/twinsparrot.gif differ diff --git a/static/img/emoji/upvoteparrot.gif b/static/img/emoji/upvoteparrot.gif new file mode 100644 index 000000000..f4c8fb417 Binary files /dev/null and b/static/img/emoji/upvoteparrot.gif differ diff --git a/static/img/emoji/vikingparrot.gif b/static/img/emoji/vikingparrot.gif new file mode 100644 index 000000000..049e112ca Binary files /dev/null and b/static/img/emoji/vikingparrot.gif differ diff --git a/static/img/emoji/wesmart.png b/static/img/emoji/wesmart.png new file mode 100644 index 000000000..5676faf23 Binary files /dev/null and b/static/img/emoji/wesmart.png differ diff --git a/static/img/emoji/wfhparrot.gif b/static/img/emoji/wfhparrot.gif new file mode 100644 index 000000000..02469db93 Binary files /dev/null and b/static/img/emoji/wfhparrot.gif differ diff --git a/static/img/emoji/wineparrot.gif b/static/img/emoji/wineparrot.gif new file mode 100644 index 000000000..e726f3c7d Binary files /dev/null and b/static/img/emoji/wineparrot.gif differ diff --git a/static/img/emoji/yoda.gif b/static/img/emoji/yoda.gif new file mode 100644 index 000000000..117958c7f Binary files /dev/null and b/static/img/emoji/yoda.gif differ diff --git a/static/img/logo.png b/static/img/logo.png new file mode 100644 index 000000000..32e5c4e6e Binary files /dev/null and b/static/img/logo.png differ diff --git a/static/metadata.html.tmpl b/static/metadata.html.tmpl deleted file mode 100644 index fb1ab7878..000000000 --- a/static/metadata.html.tmpl +++ /dev/null @@ -1,83 +0,0 @@ - - - -
- - -