diff --git a/extend/plugin_discord.go b/extend/plugin_discord.go deleted file mode 100644 index 0b5c7c66..00000000 --- a/extend/plugin_discord.go +++ /dev/null @@ -1,218 +0,0 @@ -package extend - -import ( - "bytes" - "encoding/json" - "errors" - "io/ioutil" - "log" - "net" - "net/http" - "strconv" - "strings" - "time" - - c "github.com/Azareal/Gosora/common" -) - -func init() { - c.Plugins.Add(&c.Plugin{UName: "discord", Name: "Discord", Author: "Azareal", Init: discordInit, Activate: discordActivate, Deactivate: discordDeactivate}) -} - -func discordValidate() error { - webhook, ok := c.PluginConfig["DiscordWebhook"] - if !ok || webhook == "" { - return errors.New("You need to set a webhook to push to in config.json") - } - - ev := c.PluginConfig["DiscordEvents"] - if ev != "" && ev != "threads" && ev != "replies" { - return errors.New("Invalid value for DiscordEvents. Can only be blank, 'threads' or 'replies'") - } - - fidsRaw := c.PluginConfig["DiscordForums"] - if fidsRaw != "" { - for _, fidRaw := range strings.Split(fidsRaw, ",") { - _, err := strconv.Atoi(fidRaw) - if err != nil { - return errors.New("Invalid integer found in DiscordForums") - } - } - } - - return nil -} - -func discordInit(plugin *c.Plugin) error { - err := discordValidate() - if err != nil { - return err - } - plugin.AddHook("action_end_create_topic", discordEventTopic) - plugin.AddHook("action_end_create_reply", discordEventReply) - return nil -} - -// A bit of validation to make sure the admin isn't forgetting something or telling Plugin Discord to do something absurd -func discordActivate(plugin *c.Plugin) error { - return discordValidate() -} - -func discordDeactivate(plugin *c.Plugin) { - plugin.RemoveHook("action_end_create_topic", discordEventTopic) - plugin.RemoveHook("action_end_create_reply", discordEventReply) -} - -func discordEventTopic(args ...interface{}) (skip bool, rerr c.RouteError) { - discordEvent(0, args[0].(int)) - return false, nil -} -func discordEventReply(args ...interface{}) (skip bool, rerr c.RouteError) { - discordEvent(1, args[0].(int)) - return false, nil -} - -type DiscordData struct { - Username string `json:"username"` - Embeds []DiscordEmbed `json:"embeds"` -} - -type DiscordEmbed struct { - Title string `json:"title"` - Desc string `json:"description"` - URL string `json:"url"` - Author DiscordEmbedAuthor `json:"author"` -} - -type DiscordEmbedAuthor struct { - Name string `json:"name"` - URL string `json:"url"` - Avatar string `json:"icon_url"` -} - -func discordEvent(typ int, id int) { - //fmt.Println("in discordEvent") - ev := c.PluginConfig["DiscordEvents"] - if (ev == "threads" && typ != 0) || (ev == "replies" && typ != 1) { - return - } - - var content, url string - var topic *c.Topic - var err error - var createdBy int - if typ == 0 { - topic, err = c.Topics.Get(id) - if err != nil { - return - } - content = topic.Content - createdBy = topic.CreatedBy - } else { - reply, err := c.Rstore.Get(id) - if err != nil { - return - } - content = reply.Content - createdBy = reply.CreatedBy - - topic, err = reply.Topic() - if err != nil { - return - } - } - url = topic.Link - - user, err := c.Users.Get(createdBy) - if err != nil { - return - } - - fidsRaw := c.PluginConfig["DiscordForums"] - if fidsRaw != "" { - var hasForum = false - for _, fidRaw := range strings.Split(fidsRaw, ",") { - fid, err := strconv.Atoi(fidRaw) - if err != nil { - return - } - if fid == topic.ParentID { - hasForum = true - } - } - if !hasForum { - return - } - } - if len(content) > 100 { - content = content[:97] + "..." - } - - var client = &http.Client{ - Timeout: time.Second * 10, - Transport: &http.Transport{ - Dial: (&net.Dialer{Timeout: 5 * time.Second}).Dial, - TLSHandshakeTimeout: 5 * time.Second, - }, - } - - var s string - if c.Site.EnableSsl { - s = "s" - } - var preURL = "http" + s + "://" + c.Site.URL - - var avatar = user.MicroAvatar - if len(user.MicroAvatar) > 1 { - if user.MicroAvatar[0] == '/' && user.MicroAvatar[1] != '/' { - avatar = preURL + avatar - } - } - - author := DiscordEmbedAuthor{Name: user.Name, URL: preURL + user.Link, Avatar: avatar} - embed := DiscordEmbed{Title: topic.Title, Desc: content, URL: preURL + url, Author: author} - dat := DiscordData{Username: c.Site.Name, Embeds: []DiscordEmbed{embed}} - data, err := json.Marshal(dat) - if err != nil { - c.LogWarning(err) - return - } - - //fmt.Println("before discord push") - resp, err := client.Post(c.PluginConfig["DiscordWebhook"], "application/json", bytes.NewBuffer(data)) - var body string - var respErr = func(err error) { - log.Printf("Sent: %+v\n", string(data)) - log.Printf("Response: %+v\n", resp) - if body != "" { - log.Printf("Response Body: %+v\n", body) - } - c.LogWarning(err) - } - - if err != nil { - respErr(err) - return - } - defer resp.Body.Close() - - // TODO: Cap the amount we read - bBody, err := ioutil.ReadAll(resp.Body) - if err != nil { - respErr(err) - return - } - body = string(bBody) - - if resp.StatusCode != 200 { - respErr(err) - return - } - - c.DebugLog("Pushed event to Discord") - c.DebugLogf("Sent: %+v\n", string(data)) - c.DebugLogf("Response: %+v\n", resp) - c.DebugLogf("Response Body: %+v\n", body) -} - -// TODO: Add a settings page or something? diff --git a/extend/plugin_gallery.go b/extend/plugin_gallery.go deleted file mode 100644 index a1e87f3e..00000000 --- a/extend/plugin_gallery.go +++ /dev/null @@ -1,26 +0,0 @@ -package extend - -import c "github.com/Azareal/Gosora/common" - -func init() { - c.Plugins.Add(&c.Plugin{UName: "gallery", Name: "Gallery", Author: "Azareal", URL: "https://github.com/Azareal", Init: initGallery, Deactivate: deactivateGallery}) -} - -// init_heythere is separate from init() as we don't want the plugin to run if the plugin is disabled -func initGallery(plugin *c.Plugin) error { - plugin.AddHook("topic_reply_row_assign", galleryReply) - return nil -} - -func deactivateGallery(plugin *c.Plugin) { - plugin.RemoveHook("topic_reply_row_assign", galleryReply) -} - -func galleryReply(data ...interface{}) interface{} { - currentUser := data[0].(*c.TopicPage).Header.CurrentUser - reply := data[1].(*c.ReplyUser) - reply.Content = "Hey there, " + currentUser.Name + "!" - reply.ContentHtml = "Hey there, " + currentUser.Name + "!" - reply.Tag = "Auto" - return nil -} diff --git a/extend/plugin_hyperdrive.go b/extend/plugin_hyperdrive.go deleted file mode 100644 index 321f053d..00000000 --- a/extend/plugin_hyperdrive.go +++ /dev/null @@ -1,241 +0,0 @@ -// Highly experimental plugin for caching rendered pages for guests -package extend - -import ( - //"log" - "bytes" - "errors" - "strings" - "strconv" - "time" - "sync/atomic" - "net/http" - "net/http/httptest" - - c "github.com/Azareal/Gosora/common" - "github.com/Azareal/Gosora/routes" -) - -var hyperspace *Hyperspace - -func init() { - c.Plugins.Add(&c.Plugin{UName: "hyperdrive", Name: "Hyperdrive", Author: "Azareal", Init: initHdrive, Deactivate: deactivateHdrive}) -} - -func initHdrive(plugin *c.Plugin) error { - hyperspace = newHyperspace() - plugin.AddHook("tasks_tick_topic_list",tickHdrive) - plugin.AddHook("tasks_tick_widget_wol",tickHdriveWol) - plugin.AddHook("route_topic_list_start",jumpHdriveTopicList) - plugin.AddHook("route_forum_list_start",jumpHdriveForumList) - tickHdrive() - return nil -} - -func deactivateHdrive(plugin *c.Plugin) { - plugin.RemoveHook("tasks_tick_topic_list",tickHdrive) - plugin.RemoveHook("tasks_tick_widget_wol",tickHdriveWol) - plugin.RemoveHook("route_topic_list_start",jumpHdriveTopicList) - plugin.RemoveHook("route_forum_list_start",jumpHdriveForumList) - hyperspace = nil -} - -type Hyperspace struct { - topicList atomic.Value - gzipTopicList atomic.Value - forumList atomic.Value - gzipForumList atomic.Value - lastTopicListUpdate atomic.Value -} - -func newHyperspace() *Hyperspace { - pageCache := new(Hyperspace) - blank := make(map[string][]byte,len(c.Themes)) - pageCache.topicList.Store(blank) - pageCache.gzipTopicList.Store(blank) - pageCache.forumList.Store(blank) - pageCache.gzipForumList.Store(blank) - pageCache.lastTopicListUpdate.Store(int64(0)) - return pageCache -} - -func tickHdriveWol(args ...interface{}) (skip bool, rerr c.RouteError) { - c.DebugLog("docking at wol") - return tickHdrive(args) -} - -// TODO: Find a better way of doing this -func tickHdrive(args ...interface{}) (skip bool, rerr c.RouteError) { - c.DebugLog("Refueling...") - - // Avoid accidentally caching already cached content - blank := make(map[string][]byte,len(c.Themes)) - hyperspace.topicList.Store(blank) - hyperspace.gzipTopicList.Store(blank) - hyperspace.forumList.Store(blank) - hyperspace.gzipForumList.Store(blank) - - tListMap := make(map[string][]byte) - gtListMap := make(map[string][]byte) - fListMap := make(map[string][]byte) - gfListMap := make(map[string][]byte) - - var cacheTheme = func(tname string) (skip bool, fail bool, rerr c.RouteError) { - - themeCookie := http.Cookie{Name: "current_theme", Value: tname, Path: "/", MaxAge: c.Year} - - w := httptest.NewRecorder() - req := httptest.NewRequest("get", "/topics/", bytes.NewReader(nil)) - req.AddCookie(&themeCookie) - user := c.GuestUser - - head, rerr := c.UserCheck(w, req, &user) - if rerr != nil { - return true, true, rerr - } - - rerr = routes.TopicList(w, req, user, head) - if rerr != nil { - return true, true, rerr - } - if w.Code != 200 { - c.LogWarning(errors.New("not 200 for topic list in hyperdrive")) - return false, true, nil - } - - buf := new(bytes.Buffer) - buf.ReadFrom(w.Result().Body) - tListMap[tname] = buf.Bytes() - - gbuf, err := c.CompressBytesGzip(buf.Bytes()) - if err != nil { - c.LogWarning(err) - return false, true, nil - } - gtListMap[tname] = gbuf - - w = httptest.NewRecorder() - req = httptest.NewRequest("get", "/forums/", bytes.NewReader(nil)) - user = c.GuestUser - - head, rerr = c.UserCheck(w, req, &user) - if rerr != nil { - return true, true, rerr - } - - rerr = routes.ForumList(w, req, user, head) - if rerr != nil { - return true, true, rerr - } - if w.Code != 200 { - c.LogWarning(errors.New("not 200 for forum list in hyperdrive")) - return false, true, nil - } - - buf = new(bytes.Buffer) - buf.ReadFrom(w.Result().Body) - fListMap[tname] = buf.Bytes() - - gbuf, err = c.CompressBytesGzip(buf.Bytes()) - if err != nil { - c.LogWarning(err) - return false, true, nil - } - gfListMap[tname] = gbuf - return false, false, nil - } - - for tname, _ := range c.Themes { - skip, fail, rerr := cacheTheme(tname) - if fail || rerr != nil { - return skip, rerr - } - } - - hyperspace.topicList.Store(tListMap) - hyperspace.gzipTopicList.Store(gtListMap) - hyperspace.forumList.Store(fListMap) - hyperspace.gzipForumList.Store(gfListMap) - hyperspace.lastTopicListUpdate.Store(time.Now().Unix()) - - return false, nil -} - -func jumpHdriveTopicList(args ...interface{}) (skip bool, rerr c.RouteError) { - theme := c.GetThemeByReq(args[1].(*http.Request)) - p := hyperspace.topicList.Load().(map[string][]byte) - pg := hyperspace.gzipTopicList.Load().(map[string][]byte) - return jumpHdrive(pg[theme.Name], p[theme.Name], args) -} - -func jumpHdriveForumList(args ...interface{}) (skip bool, rerr c.RouteError) { - theme := c.GetThemeByReq(args[1].(*http.Request)) - p := hyperspace.forumList.Load().(map[string][]byte) - pg := hyperspace.gzipForumList.Load().(map[string][]byte) - return jumpHdrive(pg[theme.Name], p[theme.Name], args) -} - -func jumpHdrive(pg []byte, p []byte, args []interface{}) (skip bool, rerr c.RouteError) { - var tList []byte - w := args[0].(http.ResponseWriter) - var iw http.ResponseWriter - gzw, ok := w.(c.GzipResponseWriter) - if ok { - tList = pg - iw = gzw.ResponseWriter - } else { - tList = p - iw = w - } - if len(tList) == 0 { - c.DebugLog("no itemlist in hyperspace") - return false, nil - } - //c.DebugLog("tList: ", tList) - - // Avoid intercepting user requests as we only have guests in cache right now - user := args[2].(*c.User) - if user.ID != 0 { - c.DebugLog("not guest") - return false, nil - } - - // Avoid intercepting search requests and filters as we don't have those in cache - r := args[1].(*http.Request) - //c.DebugLog("r.URL.Path:",r.URL.Path) - //c.DebugLog("r.URL.RawQuery:",r.URL.RawQuery) - if r.URL.RawQuery != "" { - return false, nil - } - if r.FormValue("js") == "1" { - return false, nil - } - //c.DebugLog - c.DebugLog("Successful jump") - - var etag string - lastUpdate := hyperspace.lastTopicListUpdate.Load().(int64) - c.DebugLog("lastUpdate:",lastUpdate) - if ok { - iw.Header().Set("X-I","1") - etag = "\""+strconv.FormatInt(lastUpdate, 10)+"-g\"" - } else { - etag = "\""+strconv.FormatInt(lastUpdate, 10)+"\"" - } - - if lastUpdate != 0 { - iw.Header().Set("ETag", etag) - if match := r.Header.Get("If-None-Match"); match != "" { - if strings.Contains(match, etag) { - iw.WriteHeader(http.StatusNotModified) - return true, nil - } - } - } - - header := args[3].(*c.Header) - routes.FootHeaders(w, header) - iw.Write(tList) - - return true, nil -} \ No newline at end of file