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