1 /++ 2 This is an example toy plugin to showcase how one could be written to react 3 to non-`!command` messages. 4 5 In the first approach (version `MatchByStringComparison`), the function is 6 annotated to be called on all channel messages, and the body has to decide 7 whether or not to react to it and reply. 8 9 In the second approach (version `MatchWithRegex`), the function is only called 10 if the incoming message matched its regular expression, so the body can safely 11 assume it should always react and reply. 12 13 See_Also: 14 [kameloso.plugins.common.core], 15 [kameloso.plugins.common.misc] 16 17 Copyright: [JR](https://github.com/zorael) 18 License: [Boost Software License 1.0](https://www.boost.org/users/license.html) 19 20 Authors: 21 [JR](https://github.com/zorael) 22 +/ 23 module kameloso.plugins.same; 24 25 version(WithSamePlugin): 26 27 // Pick *one*. 28 version = MatchByStringComparison; 29 //version = MatchWithRegex; 30 31 private: 32 33 import kameloso.plugins; 34 import kameloso.plugins.common; 35 import kameloso.messaging; 36 import dialect.defs; 37 38 39 // SameSettings 40 /++ 41 Settings for the Same plugin, to toggle it on or off. 42 +/ 43 @Settings struct SameSettings 44 { 45 /// Whether or not the Same plugin should react to events at all. 46 @Enabler bool enabled = true; 47 } 48 49 50 /+ 51 Ensure that one and only one of the matching versions is declared. 52 +/ 53 version(MatchByStringComparison) 54 { 55 version(MatchWithRegex) 56 { 57 version = MatchVersionError; 58 } 59 } 60 else version(MatchWithRegex) 61 { 62 version(MatchByStringComparison) 63 { 64 version = MatchVersionError; 65 } 66 } 67 else 68 { 69 version = MatchVersionError; 70 } 71 72 73 /+ 74 Error out during compilation if the matching versions aren't sane. 75 +/ 76 version(MatchVersionError) 77 { 78 import std.format : format; 79 80 enum pattern = "`%s` needs one of versions `MatchByStringComparison` and `MatchWithRegex` (but not both)"; 81 enum message = pattern.format(__MODULE__); 82 static assert(0, message); 83 } 84 85 86 // onAnyMessage 87 /++ 88 Reacts to the message "same" by agreeing with "same". 89 90 Uses manual matching. It is up to the function to decide whether or not it 91 should reply. 92 93 Only literal matching is made, so matches are case-sensitive and may not be 94 trailed by other text. Only messages whose contents are literally the characters 95 "same" are matched. 96 +/ 97 version(MatchByStringComparison) 98 @(IRCEventHandler() 99 .onEvent(IRCEvent.Type.CHAN) 100 .permissionsRequired(Permissions.ignore) 101 .channelPolicy(ChannelPolicy.home) 102 ) 103 void onAnyMessage(SamePlugin plugin, const ref IRCEvent event) 104 { 105 // Reply only if we should 106 if (event.content == "same") 107 { 108 chan(plugin.state, event.channel, "same"); 109 } 110 } 111 112 113 // onAnyMessageRegex 114 /++ 115 Reacts to the messages which match the text "same" with some optional 116 punctuation afterwards. 117 118 Uses the regular expression `"^same[!.]*$"`. 119 +/ 120 version(MatchWithRegex) 121 @(IRCEventHandler() 122 .onEvent(IRCEvent.Type.CHAN) 123 .permissionsRequired(Permissions.ignore) 124 .channelPolicy(ChannelPolicy.home) 125 .addRegex( 126 IRCEventHandler.Regex() 127 .policy(PrefixPolicy.direct) 128 .expression(r"^same[!.]*$") 129 .description("Same.") 130 ) 131 ) 132 void onAnyMessageRegex(SamePlugin plugin, const ref IRCEvent event) 133 { 134 // Reply always, since the function wouldn't have been called if the message didn't match 135 chan(plugin.state, event.channel, event.content); 136 } 137 138 139 mixin PluginRegistration!SamePlugin; 140 141 public: 142 143 144 // SamePlugin 145 /++ 146 The Same toy plugin, that replies to the text "same" with "same". 147 +/ 148 final class SamePlugin : IRCPlugin 149 { 150 /// All Same plugin settings gathered. 151 SameSettings sameSettings; 152 153 mixin IRCPluginImpl; 154 }