Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) 2006-2013 DMDirc Developers
  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.actions.ActionManager;
  26. import com.dmdirc.actions.CoreActionType;
  27. import com.dmdirc.addons.ui_swing.UIUtilities;
  28. import com.dmdirc.config.IdentityManager;
  29. import com.dmdirc.config.prefs.PluginPreferencesCategory;
  30. import com.dmdirc.config.prefs.PreferencesCategory;
  31. import com.dmdirc.config.prefs.PreferencesDialogModel;
  32. import com.dmdirc.config.prefs.PreferencesSetting;
  33. import com.dmdirc.config.prefs.PreferencesType;
  34. import com.dmdirc.interfaces.ActionListener;
  35. import com.dmdirc.interfaces.ConfigChangeListener;
  36. import com.dmdirc.interfaces.actions.ActionType;
  37. import com.dmdirc.parser.interfaces.ChannelClientInfo;
  38. import com.dmdirc.parser.interfaces.Parser;
  39. import com.dmdirc.parser.irc.IRCParser;
  40. import com.dmdirc.plugins.BasePlugin;
  41. import com.dmdirc.plugins.PluginInfo;
  42. import com.dmdirc.plugins.PluginManager;
  43. import java.util.ArrayList;
  44. import java.util.Date;
  45. import java.util.HashMap;
  46. import java.util.Map;
  47. import java.util.concurrent.Callable;
  48. /**
  49. * This plugin makes certain relay bots less obnoxious looking.
  50. */
  51. public class RelayBotPlugin extends BasePlugin implements ActionListener, ConfigChangeListener {
  52. /** Known RelayChannelHandlers. */
  53. private final Map<Channel, RelayChannelHandler> handlers = new HashMap<Channel, RelayChannelHandler>();
  54. /** This plugin's plugin info. */
  55. private final PluginInfo pluginInfo;
  56. /**
  57. * Creates a new instance of this plugin.
  58. *
  59. * @param pluginInfo This plugin's plugin info
  60. */
  61. public RelayBotPlugin(final PluginInfo pluginInfo) {
  62. super();
  63. this.pluginInfo = pluginInfo;
  64. }
  65. /** {@inheritDoc} */
  66. @Override
  67. public void onLoad() {
  68. ActionManager.getActionManager().registerListener(this,
  69. CoreActionType.CHANNEL_OPENED);
  70. ActionManager.getActionManager().registerListener(this,
  71. CoreActionType.CHANNEL_CLOSED);
  72. ActionManager.getActionManager().registerListener(this,
  73. CoreActionType.SERVER_CONNECTED);
  74. ActionManager.getActionManager().registerListener(this,
  75. CoreActionType.SERVER_DISCONNECTED);
  76. ActionManager.getActionManager().registerListener(this,
  77. CoreActionType.CHANNEL_QUIT);
  78. IdentityManager.getIdentityManager().getGlobalConfiguration()
  79. .addChangeListener(getDomain(), this);
  80. // Add ourself to all currently known channels that we should be
  81. // connected with.
  82. for (Server server : getPluginManager().getMain().getServerManager().getServers()) {
  83. final Parser parser = server.getParser();
  84. if (parser instanceof IRCParser && !(parser.getCallbackManager() instanceof RelayCallbackManager)) {
  85. new RelayCallbackManager(this, (IRCParser) parser);
  86. }
  87. for (String channel : server.getChannels()) {
  88. getHandler(server.getChannel(channel));
  89. }
  90. }
  91. }
  92. /**
  93. * Get our plugin manager.
  94. *
  95. * @return Our plugin manager.
  96. */
  97. protected PluginManager getPluginManager() {
  98. return pluginInfo.getMetaData().getManager();
  99. }
  100. /** {@inheritDoc} */
  101. @Override
  102. public void onUnload() {
  103. ActionManager.getActionManager().unregisterListener(this);
  104. // Remove RelayCallbackManagers
  105. for (Server server : getPluginManager().getMain().getServerManager().getServers()) {
  106. final Parser parser = server.getParser();
  107. if (parser instanceof IRCParser && parser.getCallbackManager() instanceof RelayCallbackManager) {
  108. ((RelayCallbackManager) parser.getCallbackManager()).onSocketClosed(parser, new Date());
  109. }
  110. }
  111. // Remove from all channels.
  112. synchronized (handlers) {
  113. for (RelayChannelHandler handler : new ArrayList<RelayChannelHandler>(handlers.values())) {
  114. handler.restoreCoreChannelHandler();
  115. }
  116. handlers.clear();
  117. }
  118. }
  119. /**
  120. * Process an event of the specified type.
  121. *
  122. * @param type The type of the event to process
  123. * @param format Format of messages that are about to be sent. (May be null)
  124. * @param arguments The arguments for the event
  125. */
  126. @Override
  127. public void processEvent(final ActionType type, final StringBuffer format, final Object... arguments) {
  128. if (type == CoreActionType.CHANNEL_OPENED) {
  129. getHandler((Channel) arguments[0]);
  130. } else if (type == CoreActionType.CHANNEL_CLOSED) {
  131. removeHandler((Channel) arguments[0]);
  132. } else if (type == CoreActionType.CHANNEL_QUIT) {
  133. final Channel chan = (Channel) arguments[0];
  134. final Parser parser = chan.getServer().getParser();
  135. final ChannelClientInfo cci = (ChannelClientInfo) arguments[1];
  136. final String channelName = parser.getStringConverter().toLowerCase(chan.getName());
  137. if (IdentityManager.getIdentityManager().getGlobalConfiguration().hasOptionString(getDomain(), channelName)) {
  138. final String botName = IdentityManager.getIdentityManager().getGlobalConfiguration().getOption(getDomain(), channelName);
  139. if (parser.getStringConverter().equalsIgnoreCase(botName, cci.getClient().getNickname())) {
  140. // The bot quit :(
  141. final RelayChannelHandler handler = getHandler(chan);
  142. if (handler != null) {
  143. handler.updateNames();
  144. }
  145. }
  146. }
  147. } else if (type == CoreActionType.SERVER_CONNECTED) {
  148. final Server server = (Server) arguments[0];
  149. final Parser parser = server.getParser();
  150. if (parser instanceof IRCParser && !(parser.getCallbackManager() instanceof RelayCallbackManager)) {
  151. new RelayCallbackManager(this, (IRCParser) parser);
  152. }
  153. } else if (type == CoreActionType.SERVER_DISCONNECTED) {
  154. final Server server = (Server) arguments[0];
  155. // RelayCallbackManager will revert itself when this happens.
  156. // Unset any listeners for channels of this server
  157. for (String channel : server.getChannels()) {
  158. removeHandler(server.getChannel(channel));
  159. }
  160. }
  161. }
  162. /** {@inheritDoc} */
  163. @Override
  164. public void configChanged(final String domain, final String key) {
  165. final boolean wasUnset = !IdentityManager.getIdentityManager().getGlobalConfiguration().hasOptionString(domain, key);
  166. for (Server server : getPluginManager().getMain().getServerManager().getServers()) {
  167. if (server.hasChannel(key)) {
  168. final Channel chan = server.getChannel(key);
  169. if (wasUnset) {
  170. removeHandler(chan);
  171. } else {
  172. getHandler(chan);
  173. }
  174. }
  175. }
  176. }
  177. /**
  178. * Do we have an intercept for the given channel object?
  179. * If we have one, we will return true.
  180. * If we should have one (as determined by checking the config) we will add
  181. * one and return true.
  182. *
  183. * @param channel Channel to check
  184. * @return true or false
  185. */
  186. public boolean isListening(final Channel channel) {
  187. return (getHandler(channel) != null);
  188. }
  189. /**
  190. * Get the RelayChannelHandler for a given Channel.
  191. * If we have one, we will return it.
  192. * If we should have one (as determined by checking the config) we will
  193. * create and return it.
  194. * Otherwise we will return null.
  195. *
  196. * @param channel Channel to get Handler for.
  197. * @return ChannelHandler or null
  198. */
  199. public RelayChannelHandler getHandler(final Channel channel) {
  200. synchronized (handlers) {
  201. if (handlers.containsKey(channel)) {
  202. return handlers.get(channel);
  203. } else {
  204. final String channelName = channel.getServer().getParser().getStringConverter().toLowerCase(channel.getName());
  205. if (IdentityManager.getIdentityManager().getGlobalConfiguration().hasOptionString(getDomain(), channelName)) {
  206. final RelayChannelHandler handler = new RelayChannelHandler(this, channel);
  207. handlers.put(channel, handler);
  208. return handler;
  209. }
  210. }
  211. }
  212. return null;
  213. }
  214. /**
  215. * Remove the RelayChannelHandler for a given Channel.
  216. * If we have one already, we will return it and remove it.
  217. * Otherwise we will return null.
  218. *
  219. * @param channel Channel to remove Handler for.
  220. * @return Handler that we removed, or null.
  221. */
  222. public RelayChannelHandler removeHandler(final Channel channel) {
  223. synchronized (handlers) {
  224. if (handlers.containsKey(channel)) {
  225. final RelayChannelHandler handler = handlers.get(channel);
  226. handler.unset();
  227. handlers.remove(channel);
  228. return handler;
  229. }
  230. }
  231. return null;
  232. }
  233. /**
  234. * Reads the relay bot channel data from the config.
  235. *
  236. * @return A multi-dimensional array of channel data.
  237. */
  238. public String[][] getData() {
  239. final Map<String, String> settings
  240. = IdentityManager.getIdentityManager().getGlobalConfiguration()
  241. .getOptions(getDomain());
  242. int i = 0;
  243. for (Map.Entry<String, String> entry : settings.entrySet()) {
  244. if (entry.getKey().charAt(0) == '#') {
  245. i++;
  246. }
  247. }
  248. final String[][] data = new String[i][2];
  249. i = 0;
  250. for (Map.Entry<String, String> entry : settings.entrySet()) {
  251. if (entry.getKey().charAt(0) == '#') {
  252. data[i] = new String[]{entry.getKey(), entry.getValue(), };
  253. i++;
  254. }
  255. }
  256. return data;
  257. }
  258. /** {@inheritDoc} */
  259. @Override
  260. public void showConfig(final PreferencesDialogModel manager) {
  261. final PreferencesCategory general = new PluginPreferencesCategory(
  262. pluginInfo, "Relay Bot",
  263. "General configuration for the Relay bot plugin.");
  264. final PreferencesCategory colours = new PluginPreferencesCategory(
  265. pluginInfo, "Channels",
  266. "Identifies where and who the bot is in channels.",
  267. UIUtilities.invokeAndWait(
  268. new Callable<RelayChannelPanel>() {
  269. /** {@inheritDoc} */
  270. @Override
  271. public RelayChannelPanel call() {
  272. return new RelayChannelPanel(getPluginManager()
  273. .getPluginInfoByName("ui_swing").getPlugin(),
  274. RelayBotPlugin.this);
  275. }
  276. }));
  277. colours.setInline().setInlineAfter();
  278. general.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  279. getDomain(), "joinOnDiscover", "Join on discover",
  280. "Do you want fake clients to join the channel?",
  281. manager.getConfigManager(), manager.getIdentity()));
  282. general.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  283. getDomain(), "colourFullName", "Colour full name",
  284. "Do you want to colour the full name?",
  285. manager.getConfigManager(), manager.getIdentity()));
  286. manager.getCategory("Plugins").addSubCategory(general);
  287. general.addSubCategory(colours);
  288. }
  289. }