You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RelayBotPlugin.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.addons.relaybot;
  23. import com.dmdirc.Channel;
  24. import com.dmdirc.Server;
  25. import com.dmdirc.ServerManager;
  26. import com.dmdirc.actions.ActionManager;
  27. import com.dmdirc.actions.CoreActionType;
  28. import com.dmdirc.actions.interfaces.ActionType;
  29. import com.dmdirc.addons.ui_swing.UIUtilities;
  30. import com.dmdirc.config.IdentityManager;
  31. import com.dmdirc.config.prefs.PluginPreferencesCategory;
  32. import com.dmdirc.config.prefs.PreferencesCategory;
  33. import com.dmdirc.config.prefs.PreferencesDialogModel;
  34. import com.dmdirc.config.prefs.PreferencesSetting;
  35. import com.dmdirc.config.prefs.PreferencesType;
  36. import com.dmdirc.interfaces.ActionListener;
  37. import com.dmdirc.interfaces.ConfigChangeListener;
  38. import com.dmdirc.parser.interfaces.ChannelClientInfo;
  39. import com.dmdirc.parser.interfaces.Parser;
  40. import com.dmdirc.parser.irc.IRCParser;
  41. import com.dmdirc.plugins.Plugin;
  42. import com.dmdirc.plugins.PluginManager;
  43. import com.dmdirc.util.ReturnableThread;
  44. import java.util.ArrayList;
  45. import java.util.Date;
  46. import java.util.HashMap;
  47. import java.util.Map;
  48. /**
  49. * This plugin makes certain relay bots less obnoxious looking.
  50. *
  51. * @author shane
  52. */
  53. public class RelayBotPlugin extends Plugin implements ActionListener, ConfigChangeListener {
  54. /** Known RelayChannelHandlers. */
  55. private final Map<Channel, RelayChannelHandler> handlers = new HashMap<Channel, RelayChannelHandler>();
  56. /**
  57. * Creates a new instance of the RelayBotPlugin.
  58. */
  59. public RelayBotPlugin() {
  60. super();
  61. }
  62. /** {@inheritDoc} */
  63. @Override
  64. public void onLoad() {
  65. ActionManager.addListener(this, CoreActionType.CHANNEL_OPENED);
  66. ActionManager.addListener(this, CoreActionType.CHANNEL_CLOSED);
  67. ActionManager.addListener(this, CoreActionType.SERVER_CONNECTED);
  68. ActionManager.addListener(this, CoreActionType.SERVER_DISCONNECTED);
  69. ActionManager.addListener(this, CoreActionType.CHANNEL_QUIT);
  70. IdentityManager.getGlobalConfig().addChangeListener(getDomain(), this);
  71. // Add ourself to all currently known channels that we should be
  72. // connected with.
  73. for (Server server : ServerManager.getServerManager().getServers()) {
  74. final Parser parser = server.getParser();
  75. if (parser instanceof IRCParser && !(parser.getCallbackManager() instanceof RelayCallbackManager)) {
  76. new RelayCallbackManager(this, (IRCParser) parser);
  77. }
  78. for (String channel : server.getChannels()) {
  79. getHandler(server.getChannel(channel));
  80. }
  81. }
  82. }
  83. /** {@inheritDoc} */
  84. @Override
  85. public void onUnload() {
  86. ActionManager.removeListener(this);
  87. // Remove RelayCallbackManagers
  88. for (Server server : ServerManager.getServerManager().getServers()) {
  89. final Parser parser = server.getParser();
  90. if (parser instanceof IRCParser && parser.getCallbackManager() instanceof RelayCallbackManager) {
  91. ((RelayCallbackManager) parser.getCallbackManager()).onSocketClosed(parser, new Date());
  92. }
  93. }
  94. // Remove from all channels.
  95. synchronized (handlers) {
  96. for (RelayChannelHandler handler : new ArrayList<RelayChannelHandler>(handlers.values())) {
  97. handler.restoreCoreChannelHandler();
  98. }
  99. handlers.clear();
  100. }
  101. }
  102. /**
  103. * Process an event of the specified type.
  104. *
  105. * @param type The type of the event to process
  106. * @param format Format of messages that are about to be sent. (May be null)
  107. * @param arguments The arguments for the event
  108. */
  109. @Override
  110. public void processEvent(final ActionType type, final StringBuffer format, final Object... arguments) {
  111. if (type == CoreActionType.CHANNEL_OPENED) {
  112. getHandler((Channel) arguments[0]);
  113. } else if (type == CoreActionType.CHANNEL_CLOSED) {
  114. removeHandler((Channel) arguments[0]);
  115. } else if (type == CoreActionType.CHANNEL_QUIT) {
  116. final Channel chan = (Channel) arguments[0];
  117. final Parser parser = chan.getServer().getParser();
  118. final ChannelClientInfo cci = (ChannelClientInfo) arguments[1];
  119. final String channelName = parser.getStringConverter().toLowerCase(chan.getName());
  120. if (IdentityManager.getGlobalConfig().hasOptionString(getDomain(), channelName)) {
  121. final String botName = IdentityManager.getGlobalConfig().getOption(getDomain(), channelName);
  122. if (parser.getStringConverter().equalsIgnoreCase(botName, cci.getClient().getNickname())) {
  123. // The bot quit :(
  124. final RelayChannelHandler handler = getHandler(chan);
  125. if (handler != null) {
  126. handler.updateNames();
  127. }
  128. }
  129. }
  130. } else if (type == CoreActionType.SERVER_CONNECTED) {
  131. final Server server = (Server) arguments[0];
  132. final Parser parser = server.getParser();
  133. if (parser instanceof IRCParser && !(parser.getCallbackManager() instanceof RelayCallbackManager)) {
  134. new RelayCallbackManager(this, (IRCParser) parser);
  135. }
  136. } else if (type == CoreActionType.SERVER_DISCONNECTED) {
  137. final Server server = (Server) arguments[0];
  138. // RelayCallbackManager will revert itself when this happens.
  139. // Unset any listeners for channels of this server
  140. for (String channel : server.getChannels()) {
  141. removeHandler(server.getChannel(channel));
  142. }
  143. }
  144. }
  145. /** {@inheritDoc} */
  146. @Override
  147. public void configChanged(final String domain, final String key) {
  148. final boolean wasUnset = !IdentityManager.getGlobalConfig().hasOptionString(domain, key);
  149. for (Server server : ServerManager.getServerManager().getServers()) {
  150. if (server.hasChannel(key)) {
  151. final Channel chan = server.getChannel(key);
  152. if (wasUnset) {
  153. removeHandler(chan);
  154. } else {
  155. getHandler(chan);
  156. }
  157. }
  158. }
  159. }
  160. /**
  161. * Do we have an intercept for the given channel object?
  162. * If we have one, we will return true.
  163. * If we should have one (as determined by checking the config) we will add
  164. * one and return true.
  165. *
  166. * @param channel Channel to check
  167. * @return true or false
  168. */
  169. public boolean isListening(final Channel channel) {
  170. return (getHandler(channel) != null);
  171. }
  172. /**
  173. * Get the RelayChannelHandler for a given Channel.
  174. * If we have one, we will return it.
  175. * If we should have one (as determined by checking the config) we will
  176. * create and return it.
  177. * Otherwise we will return null.
  178. *
  179. * @param channel Channel to get Handler for.
  180. * @return ChannelHandler or null
  181. */
  182. public RelayChannelHandler getHandler(final Channel channel) {
  183. synchronized (handlers) {
  184. if (handlers.containsKey(channel)) {
  185. return handlers.get(channel);
  186. } else {
  187. final String channelName = channel.getServer().getParser().getStringConverter().toLowerCase(channel.getName());
  188. if (IdentityManager.getGlobalConfig().hasOptionString(getDomain(), channelName)) {
  189. final RelayChannelHandler handler = new RelayChannelHandler(this, channel);
  190. handlers.put(channel, handler);
  191. return handler;
  192. }
  193. }
  194. }
  195. return null;
  196. }
  197. /**
  198. * Remove the RelayChannelHandler for a given Channel.
  199. * If we have one already, we will return it and remove it.
  200. * Otherwise we will return null.
  201. *
  202. * @param channel Channel to remove Handler for.
  203. * @return Handler that we removed, or null.
  204. */
  205. public RelayChannelHandler removeHandler(final Channel channel) {
  206. synchronized (handlers) {
  207. if (handlers.containsKey(channel)) {
  208. final RelayChannelHandler handler = handlers.get(channel);
  209. handler.unset();
  210. handlers.remove(channel);
  211. return handler;
  212. }
  213. }
  214. return null;
  215. }
  216. /**
  217. * Reads the relay bot channel data from the config.
  218. *
  219. * @return A multi-dimensional array of channel data.
  220. */
  221. public String[][] getData() {
  222. final Map<String, String> settings = IdentityManager.getGlobalConfig()
  223. .getOptions(getDomain());
  224. int i = 0;
  225. for (Map.Entry<String, String> entry : settings.entrySet()) {
  226. if (entry.getKey().charAt(0) == '#') {
  227. i++;
  228. }
  229. }
  230. final String[][] data = new String[i][2];
  231. i = 0;
  232. for (Map.Entry<String, String> entry : settings.entrySet()) {
  233. if (entry.getKey().charAt(0) == '#') {
  234. data[i] = new String[]{entry.getKey(), entry.getValue(), };
  235. i++;
  236. }
  237. }
  238. return data;
  239. }
  240. /** {@inheritDoc} */
  241. @Override
  242. public void showConfig(final PreferencesDialogModel manager) {
  243. final PreferencesCategory general = new PluginPreferencesCategory(
  244. getPluginInfo(), "Relay Bot",
  245. "General configuration for the Relay bot plugin.");
  246. final PreferencesCategory colours = new PluginPreferencesCategory(
  247. getPluginInfo(), "Channels",
  248. "Identifies where and who the bot is in channels.",
  249. UIUtilities.invokeAndWait(
  250. new ReturnableThread<RelayChannelPanel>() {
  251. /** {@inheritDoc} */
  252. @Override
  253. public void run() {
  254. setObject(new RelayChannelPanel(PluginManager.getPluginManager()
  255. .getPluginInfoByName("ui_swing").getPlugin(),
  256. RelayBotPlugin.this));
  257. }
  258. }));
  259. colours.setInline().setInlineAfter();
  260. general.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  261. getDomain(), "joinOnDiscover", "Join on discover",
  262. "Do you want fake clients to join the channel?"));
  263. general.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  264. getDomain(), "colourFullName", "Colour full name",
  265. "Do you want to colour the full name?"));
  266. manager.getCategory("Plugins").addSubCategory(general);
  267. general.addSubCategory(colours);
  268. }
  269. }