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