1 package sriracha 2 3 import ( 4 "fmt" 5 "html/template" 6 "mime/multipart" 7 "net/http" 8 "strings" 9 10 . "codeberg.org/tslocum/sriracha/model" 11 . "codeberg.org/tslocum/sriracha/util" 12 ) 13 14 // PluginConfigType represents the type of a plugin configuration option. 15 type PluginConfigType int 16 17 // Plugin config types. 18 const ( 19 TypeBoolean PluginConfigType = 0 20 TypeInteger PluginConfigType = 1 21 TypeFloat PluginConfigType = 2 22 TypeEnum PluginConfigType = 3 23 TypeString PluginConfigType = 4 24 TypeBoard PluginConfigType = 5 25 ) 26 27 // PluginConfig represents a plugin configuration option. 28 type PluginConfig struct { 29 Type PluginConfigType 30 Multiple bool 31 Name string 32 Info string 33 Value string 34 Default string 35 Sensitive bool // Sensitive options are excluded from the audit log. 36 } 37 38 func (c PluginConfig) Validate() error { 39 switch { 40 case strings.TrimSpace(c.Name) == "": 41 return fmt.Errorf("name must be set") 42 case c.Type < TypeBoolean || c.Type > TypeBoard: 43 return fmt.Errorf("invalid type") 44 case c.Type == TypeBoolean && c.Multiple: 45 return fmt.Errorf("multi-value boolean options are not allowed") 46 default: 47 return nil 48 } 49 } 50 51 // Options returns the options of the provided configuration option as a collection of strings. 52 func (c PluginConfig) Options() []string { 53 if c.Type != TypeEnum { 54 return nil 55 } 56 return strings.Split(c.Default, "|||") 57 } 58 59 // Values returns the value of the provided configuration option as a collection of strings. 60 func (c PluginConfig) Values() []string { 61 if c.Value == "" { 62 return nil 63 } else if !c.Multiple { 64 return []string{c.Value} 65 } 66 return strings.Split(c.Value, "|||") 67 } 68 69 // HaveInt returns whether an integer value is selected. 70 func (c PluginConfig) HaveInt(i int) bool { 71 for _, v := range c.Values() { 72 if ParseInt(v) == i { 73 return true 74 } 75 } 76 return false 77 } 78 79 // Plugin describes the required methods for a plugin. 80 type Plugin interface { 81 // About returns the plugin description. 82 About() string 83 } 84 85 // PluginWithHelp describes the required methods for a plugin with help text. 86 type PluginWithHelp interface { 87 // Help returns the text displayed above the available configuration options. 88 Help() template.HTML 89 } 90 91 // PluginWithConfig describes the required methods for a plugin with configuration options. 92 type PluginWithConfig interface { 93 Plugin 94 95 // Config returns the available configuration options. 96 Config() []PluginConfig 97 } 98 99 // PluginWithUpdate describes the required methods for a plugin subscribing to configuration updates. 100 type PluginWithUpdate interface { 101 Plugin 102 103 // Update events are sent when a configuration option is modified. Update events 104 // are also sent for each configuration option when the server initializes. 105 Update(db DB, key string) error 106 } 107 108 // PluginWithRules describes the required methods for a plugin with text displayed below the post form. 109 type PluginWithRules interface { 110 Plugin 111 112 // Rules returns text informing visitors of available features and functionality. 113 // This text is displayed below the post form in board index and thread pages. 114 Rules(db DB, board *Board) (template.HTML, error) 115 } 116 117 // PluginWithAttach describes the required methods for a plugin subscribing to attach events. 118 type PluginWithAttach interface { 119 Plugin 120 121 // Attach events are sent when a file is attached to a post. FileOriginal contains 122 // the original file name and FileMIME contains the detected MIME type. When a 123 // file attachment is handled, return true to stop propagating events. 124 Attach(db DB, post *Post, file multipart.File) (handled bool, err error) 125 } 126 127 // PluginWithEmbed describes the required methods for a plugin subscribing to embed events. 128 type PluginWithEmbed interface { 129 Plugin 130 131 // Embed events are sent when a URL is embedded in a post. When an embed URL 132 // is handled, return true to stop propagating events. 133 Embed(db DB, post *Post, embedURL string) (handled bool, err error) 134 } 135 136 // PluginWithPost describes the required methods for a plugin subscribing to post events. 137 type PluginWithPost interface { 138 Plugin 139 140 // Post events are sent when a new post is being created. Message is the 141 // only HTML-escaped field. Newlines are conveted into line break tags 142 // after all plugins have finished processing the post. 143 Post(db DB, post *Post) error 144 } 145 146 // PluginWithInsert describes the required methods for a plugin subscribing to insert events. 147 type PluginWithInsert interface { 148 Plugin 149 150 // Insert events are sent after Post events have been processed, before a 151 // new post is inserted. The post may not be modified during this event. 152 // Modify new posts during a Post event instead. Return an error to cancel 153 // the post, or nil to continue processing. 154 Insert(db DB, post *Post) error 155 } 156 157 // PluginWithCreate describes the required methods for a plugin subscribing to create events. 158 type PluginWithCreate interface { 159 Plugin 160 161 // Create events are sent when a new post is created and inserted into the 162 // database, after Post and Insert events have been processed. The post may 163 // not be modified during this event. Modify posts during a Post event instead. 164 Create(db DB, post *Post) error 165 } 166 167 // PluginWithReport describes the required methods for a plugin subscribing to report events. 168 type PluginWithReport interface { 169 Plugin 170 171 // Report events are sent when a post is reported. 172 Report(db DB, post *Post) error 173 } 174 175 // PluginWithAudit describes the required methods for a plugin subscribing to audit events. 176 type PluginWithAudit interface { 177 Plugin 178 179 // Audit events are sent when a new message is added to the audit log. 180 // Based on the source of the event, user is "system", "admin" or "mod". 181 Audit(db DB, user string, action string, info string) error 182 } 183 184 // PluginWithServe describes the required methods for a plugin with a web interface. 185 type PluginWithServe interface { 186 Plugin 187 188 // Serve handles plugin web requests. Only administrators and super-administrators 189 // may access this page. When serving HTML responses, return the HTML and a 190 // nil error. When serving any other content type, set the Conent-Type header, 191 // write to the http.ResponseWriter directly and return a blank string. 192 Serve(db DB, a *Account, w http.ResponseWriter, r *http.Request) (template.HTML, error) 193 } 194