diff --git a/vilebot/pom.xml b/vilebot/pom.xml
index 52cc8a70..16dd478c 100644
--- a/vilebot/pom.xml
+++ b/vilebot/pom.xml
@@ -8,6 +8,7 @@
UTF-8
+ 2.3.2
@@ -163,5 +164,18 @@
commons-text
1.6
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ ${jaxb.version}
+
+
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ ${jaxb.version}
+
diff --git a/vilebot/src/main/java/com/oldterns/vilebot/Vilebot.java b/vilebot/src/main/java/com/oldterns/vilebot/Vilebot.java
index 80a11bb4..8dae900c 100644
--- a/vilebot/src/main/java/com/oldterns/vilebot/Vilebot.java
+++ b/vilebot/src/main/java/com/oldterns/vilebot/Vilebot.java
@@ -6,10 +6,56 @@
*/
package com.oldterns.vilebot;
-import com.oldterns.vilebot.handlers.admin.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import com.oldterns.vilebot.handlers.admin.AdminManagement;
+import com.oldterns.vilebot.handlers.admin.AdminPing;
+import com.oldterns.vilebot.handlers.admin.Auth;
+import com.oldterns.vilebot.handlers.admin.GetLog;
+import com.oldterns.vilebot.handlers.admin.NickChange;
+import com.oldterns.vilebot.handlers.admin.Quit;
+import com.oldterns.vilebot.handlers.user.AnswerQuestion;
+import com.oldterns.vilebot.handlers.user.Ascii;
+import com.oldterns.vilebot.handlers.user.ChatLogger;
+import com.oldterns.vilebot.handlers.user.Church;
+import com.oldterns.vilebot.handlers.user.Countdown;
+import com.oldterns.vilebot.handlers.user.Decide;
+import com.oldterns.vilebot.handlers.user.Excuses;
+import com.oldterns.vilebot.handlers.user.FakeNews;
+import com.oldterns.vilebot.handlers.user.FoobarNews;
+import com.oldterns.vilebot.handlers.user.Fortune;
+import com.oldterns.vilebot.handlers.user.GetInfoOn;
import com.oldterns.vilebot.handlers.user.Help;
+import com.oldterns.vilebot.handlers.user.ImageToAscii;
+import com.oldterns.vilebot.handlers.user.Inspiration;
+import com.oldterns.vilebot.handlers.user.Jaziz;
+import com.oldterns.vilebot.handlers.user.Jokes;
+import com.oldterns.vilebot.handlers.user.Kaomoji;
+import com.oldterns.vilebot.handlers.user.Karma;
+import com.oldterns.vilebot.handlers.user.KarmaRoll;
+import com.oldterns.vilebot.handlers.user.LastMessageSed;
+import com.oldterns.vilebot.handlers.user.LastSeen;
+import com.oldterns.vilebot.handlers.user.Markov;
+import com.oldterns.vilebot.handlers.user.News;
+import com.oldterns.vilebot.handlers.user.Omgword;
import com.oldterns.vilebot.handlers.user.Ops;
-import com.oldterns.vilebot.handlers.user.*;
+import com.oldterns.vilebot.handlers.user.QuotesAndFacts;
+import com.oldterns.vilebot.handlers.user.RemindMe;
+import com.oldterns.vilebot.handlers.user.RockPaperScissors;
+import com.oldterns.vilebot.handlers.user.Trivia;
+import com.oldterns.vilebot.handlers.user.Ttc;
+import com.oldterns.vilebot.handlers.user.TwitterCorrection;
+import com.oldterns.vilebot.handlers.user.UrlTitleAnnouncer;
+import com.oldterns.vilebot.handlers.user.UrlTweetAnnouncer;
+import com.oldterns.vilebot.handlers.user.UserPing;
+import com.oldterns.vilebot.handlers.user.Userlists;
+import com.oldterns.vilebot.handlers.user.Weather;
import com.oldterns.vilebot.util.BaseNick;
import org.pircbotx.Configuration;
import org.pircbotx.MultiBotManager;
@@ -21,14 +67,6 @@
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
public class Vilebot
extends ListenerAdapter
{
@@ -78,7 +116,7 @@ public static void main( String[] args )
Configuration botConfiguration =
new Configuration.Builder().setName( ircNick ).setLogin( ircUser ).setRealName( ircRealName ).addServer( ircServerAddress,
- ircPort ).addAutoJoinChannel( ircChannel ).setAutoReconnect( true ).addListener( new Vilebot() ).addListener( new AdminManagement() ).addListener( new AdminPing() ).addListener( new Auth() ).addListener( new GetLog() ).addListener( new com.oldterns.vilebot.handlers.admin.Help() ).addListener( new NickChange() ).addListener( new com.oldterns.vilebot.handlers.admin.Ops() ).addListener( new Quit() ).addListener( new AnswerQuestion() ).addListener( new Ascii() ).addListener( new ChatLogger() ).addListener( new Church() ).addListener( new Countdown() ).addListener( new Decide() ).addListener( new Excuses() ).addListener( new FakeNews() ).addListener( new Fortune() ).addListener( new GetInfoOn() ).addListener( new Help() ).addListener( new ImageToAscii() ).addListener( new Inspiration() ).addListener( new Jaziz() ).addListener( new Jokes() ).addListener( new Kaomoji() ).addListener( new Karma() ).addListener( new KarmaRoll() ).addListener( new LastMessageSed() ).addListener( new LastSeen() ).addListener( new Markov() ).addListener( new News() ).addListener( new Omgword() ).addListener( new Ops() ).addListener( new QuotesAndFacts() ).addListener( new RemindMe() ).addListener( new RockPaperScissors() ).addListener( new Trivia() ).addListener( new Ttc() ).addListener( new TwitterCorrection() ).addListener( new UrlTitleAnnouncer() ).addListener( new UrlTweetAnnouncer() ).addListener( new Userlists() ).addListener( new UserPing() ).addListener( new Weather() ).buildConfiguration();
+ ircPort ).addAutoJoinChannel( ircChannel ).setAutoReconnect( true ).addListener( new Vilebot() ).addListener( new AdminManagement() ).addListener( new AdminPing() ).addListener( new Auth() ).addListener( new GetLog() ).addListener( new com.oldterns.vilebot.handlers.admin.Help() ).addListener( new NickChange() ).addListener( new com.oldterns.vilebot.handlers.admin.Ops() ).addListener( new Quit() ).addListener( new AnswerQuestion() ).addListener( new Ascii() ).addListener( new ChatLogger() ).addListener( new Church() ).addListener( new Countdown() ).addListener( new Decide() ).addListener( new Excuses() ).addListener( new FakeNews() ).addListener( new Fortune() ).addListener( new GetInfoOn() ).addListener( new Help() ).addListener( new ImageToAscii() ).addListener( new Inspiration() ).addListener( new Jaziz() ).addListener( new Jokes() ).addListener( new Kaomoji() ).addListener( new Karma() ).addListener( new KarmaRoll() ).addListener( new LastMessageSed() ).addListener( new LastSeen() ).addListener( new Markov() ).addListener( new News() ).addListener( new Omgword() ).addListener( new Ops() ).addListener( new QuotesAndFacts() ).addListener( new RemindMe() ).addListener( new RockPaperScissors() ).addListener( new Trivia() ).addListener( new Ttc() ).addListener( new TwitterCorrection() ).addListener( new UrlTitleAnnouncer() ).addListener( new UrlTweetAnnouncer() ).addListener( new Userlists() ).addListener( new UserPing() ).addListener( new Weather() ).addListener( new FoobarNews() ).buildConfiguration();
botManager.addBot( botConfiguration );
}
diff --git a/vilebot/src/main/java/com/oldterns/vilebot/db/QuoteFactDB.java b/vilebot/src/main/java/com/oldterns/vilebot/db/QuoteFactDB.java
index abb83ea4..8125e9a3 100644
--- a/vilebot/src/main/java/com/oldterns/vilebot/db/QuoteFactDB.java
+++ b/vilebot/src/main/java/com/oldterns/vilebot/db/QuoteFactDB.java
@@ -6,9 +6,11 @@
*/
package com.oldterns.vilebot.db;
-import java.util.Set;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
import redis.clients.jedis.Jedis;
@@ -21,6 +23,25 @@ public class QuoteFactDB
private static final int COUNT = 5;
+ public static Set getQuotableFactableNicks()
+ {
+ Jedis jedis = pool.getResource();
+ try
+ {
+ Set hasQuotes = jedis.keys( keyOfQuoteSetsPrefix + "*" );
+ Set hasFacts = jedis.keys( keyOfFactSetsPrefix + "*" );
+
+ Set out = new HashSet<>();
+ out.addAll( hasQuotes.stream().map( s -> s.substring( keyOfQuoteSetsPrefix.length() ) ).collect( Collectors.toSet() ) );
+ out.addAll( hasFacts.stream().map( s -> s.substring( keyOfFactSetsPrefix.length() ) ).collect( Collectors.toSet() ) );
+ return out;
+ }
+ finally
+ {
+ pool.returnResource( jedis );
+ }
+ }
+
/**
* Add a quote to the quote set of a noun.
*
diff --git a/vilebot/src/main/java/com/oldterns/vilebot/handlers/user/FoobarNews.java b/vilebot/src/main/java/com/oldterns/vilebot/handlers/user/FoobarNews.java
new file mode 100644
index 00000000..166a8d56
--- /dev/null
+++ b/vilebot/src/main/java/com/oldterns/vilebot/handlers/user/FoobarNews.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2019 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.oldterns.vilebot.handlers.user;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import com.oldterns.vilebot.Vilebot;
+import com.oldterns.vilebot.db.QuoteFactDB;
+import com.oldterns.vilebot.util.LimitCommand;
+import com.oldterns.vilebot.util.NewsParser;
+import com.oldterns.vilebot.util.rss.Channel;
+import com.oldterns.vilebot.util.rss.Item;
+import com.oldterns.vilebot.util.rss.RSS;
+import org.pircbotx.hooks.types.GenericMessageEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FoobarNews
+ extends NewsParser
+{
+ private static final Pattern FOOBAR_NEWS_PATTERN = Pattern.compile( "^!foobarnews(?: ([a-zA-Z]+)|)" );
+
+ private static final Pattern FOOBAR_NEWS_HELP_PATTERN = Pattern.compile( "^!foobarnews help" );
+
+ private static final Logger logger = LoggerFactory.getLogger( FoobarNews.class );
+
+ private final String HELP_MESSAGE = generateHelpMessage();
+
+ private final String HELP_COMMAND = "'!news help'";
+
+ public static LimitCommand limitCommand = new LimitCommand( 100, 1 );
+
+ private static final String RESTRICTED_CHANNEL = Vilebot.getConfig().get( "ircChannel1" );
+
+ @Override
+ public void onGenericMessage( final GenericMessageEvent event )
+ {
+ String text = event.getMessage();
+ Matcher matcher = FOOBAR_NEWS_PATTERN.matcher( text );
+ Matcher helpMatcher = FOOBAR_NEWS_HELP_PATTERN.matcher( text );
+
+ if ( helpMatcher.matches() )
+ {
+ for ( String line : HELP_MESSAGE.split( "\n" ) )
+ {
+ event.respondPrivateMessage( line );
+ }
+ }
+ else if ( matcher.matches() )
+ {
+ String category = matcher.group( 1 );
+ if ( category != null && category.equals( "foobar" ) )
+ {
+ category = null;
+ }
+ else if ( category != null && !QuoteFactDB.getQuotableFactableNicks().contains( category ) )
+ {
+ event.respond( category + " is not a nick that has facts or quotes." );
+ return;
+ }
+ HashMap newsFeedsByCategory = new HashMap<>();
+ try
+ {
+ Path newsFile = Files.createTempFile( "FoobarNews", ".xml" );
+ logger.info( "Foobar news temp file: " + newsFile.toString() );
+
+ RSS rssFeed = createRssFeed( category );
+ JAXBContext context = JAXBContext.newInstance( RSS.class );
+ Marshaller marshaller = context.createMarshaller();
+ try ( FileOutputStream fileOutputStream = new FileOutputStream( newsFile.toFile() ) )
+ {
+ marshaller.marshal( rssFeed, fileOutputStream );
+ URL newsFileURL = newsFile.toUri().toURL();
+ category = ( category != null ) ? category.toLowerCase() : "foobar";
+
+ newsFeedsByCategory.put( category, newsFileURL );
+ logger.info( newsFileURL.toString() );
+ currentNews( event, matcher, newsFeedsByCategory, category, HELP_COMMAND, limitCommand,
+ RESTRICTED_CHANNEL, logger );
+ }
+ catch ( IOException e )
+ {
+ throw e;
+ }
+ }
+ catch ( IOException | JAXBException e )
+ {
+ event.respond( "I could not create temporary file for the news :(" );
+ }
+ }
+ }
+
+ private RSS createRssFeed( String topic )
+ {
+ final int ITEM_COUNT = 3;
+ final String VERSION = "2.0";
+
+ RSS out = new RSS();
+ out.version = VERSION;
+
+ Channel channel = new Channel();
+ channel.title = "The Foobar News";
+ channel.link = "http://localhost";
+ channel.description = "The latest in #thefoobar";
+ channel.items = new ArrayList<>();
+
+ Markov markov = new Markov();
+ if ( topic != null )
+ {
+ markov.trainOnNick( topic );
+ }
+ else
+ {
+ markov.train();
+ }
+
+ for ( int i = 0; i < ITEM_COUNT; i++ )
+ {
+ Item item = new Item();
+ item.title = markov.generatePhrase( 50 );
+ item.link = "http://localhost";
+ item.description = "";
+ channel.items.add( item );
+ }
+
+ out.channel = channel;
+ return out;
+ }
+
+ @Override
+ protected String generateHelpMessage()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append( "Foobar News Categories (example: !foobarnews foobar):" );
+ sb.append( "\n" );
+
+ sb.append( " { foobar }" );
+ for ( String nick : QuoteFactDB.getQuotableFactableNicks() )
+ {
+ sb.append( " { " + nick + " }" );
+ }
+
+ return sb.toString();
+ }
+
+}
diff --git a/vilebot/src/main/java/com/oldterns/vilebot/handlers/user/Markov.java b/vilebot/src/main/java/com/oldterns/vilebot/handlers/user/Markov.java
index 6c396bc9..6af459f8 100644
--- a/vilebot/src/main/java/com/oldterns/vilebot/handlers/user/Markov.java
+++ b/vilebot/src/main/java/com/oldterns/vilebot/handlers/user/Markov.java
@@ -1,18 +1,20 @@
package com.oldterns.vilebot.handlers.user;
-import com.oldterns.vilebot.db.LogDB;
-import com.oldterns.vilebot.util.MangleNicks;
-import com.oldterns.vilebot.util.Zalgo;
-import org.pircbotx.hooks.ListenerAdapter;
-import org.pircbotx.hooks.types.GenericMessageEvent;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import java.util.Set;
import java.util.regex.Pattern;
+import com.oldterns.vilebot.db.LogDB;
+import com.oldterns.vilebot.db.QuoteFactDB;
+import com.oldterns.vilebot.util.MangleNicks;
+import com.oldterns.vilebot.util.Zalgo;
+import org.pircbotx.hooks.ListenerAdapter;
+import org.pircbotx.hooks.types.GenericMessageEvent;
+
/**
* Created by emmett on 12/08/15.
*/
@@ -48,12 +50,22 @@ public void onGenericMessage( final GenericMessageEvent event )
}
}
- private void train()
+ protected void train()
{
String data = LogDB.getLog();
fillMarkovMap( data );
}
+ protected void trainOnNick( String nick )
+ {
+ Set quotes = QuoteFactDB.getQuotes( nick );
+ Set facts = QuoteFactDB.getFacts( nick );
+ StringBuilder trainingData = new StringBuilder();
+ quotes.forEach( q -> trainingData.append( q ).append( "\n" ) );
+ facts.forEach( f -> trainingData.append( f ).append( "\n" ) );
+ fillMarkovMap( trainingData.toString() );
+ }
+
private void fillMarkovMap( String data )
{
String[] words = data.split( "\\s+" );
@@ -80,7 +92,7 @@ else if ( markovMap.get( key ) != null )
}
}
- private String generatePhrase()
+ protected String generatePhrase()
{
Random random = new Random();
String key = getRandomKey( random );
@@ -99,6 +111,55 @@ private String generatePhrase()
return phrase.toString().replace( "\n", " " );
}
+ protected String generatePhrase( String topic )
+ {
+ Random random = new Random();
+ String key = topic;
+ StringBuilder phrase = new StringBuilder();
+
+ while ( key != null && phrase.length() < 1000 )
+ {
+ phrase.append( key ).append( " " );
+ if ( shouldEnd( key ) )
+ {
+ break;
+ }
+ key = nextKey( key, random );
+ }
+
+ return phrase.toString().replace( "\n", " " );
+ }
+
+ protected String generatePhrase( String topic, int idealLength )
+ {
+ Random random = new Random();
+ String key = topic;
+ StringBuilder phrase = new StringBuilder();
+
+ while ( key != null && phrase.length() < idealLength )
+ {
+ phrase.append( key ).append( " " );
+ key = nextKey( key, random );
+ }
+
+ return phrase.toString().replace( "\n", " " );
+ }
+
+ protected String generatePhrase( int idealLength )
+ {
+ Random random = new Random();
+ String key = getRandomKey( random );
+ StringBuilder phrase = new StringBuilder();
+
+ while ( key != null && phrase.length() < idealLength )
+ {
+ phrase.append( key ).append( " " );
+ key = nextKey( key, random );
+ }
+
+ return phrase.toString().replace( "\n", " " );
+ }
+
private String nextKey( String key, Random random )
{
List valueList = markovMap.get( key );
diff --git a/vilebot/src/main/java/com/oldterns/vilebot/util/rss/Channel.java b/vilebot/src/main/java/com/oldterns/vilebot/util/rss/Channel.java
new file mode 100644
index 00000000..4d920fb6
--- /dev/null
+++ b/vilebot/src/main/java/com/oldterns/vilebot/util/rss/Channel.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.oldterns.vilebot.util.rss;
+
+import java.util.ArrayList;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType( XmlAccessType.FIELD )
+@XmlType( name = "channel" )
+public class Channel
+{
+ @XmlElement( name = "title" )
+ public String title;
+
+ @XmlElement( name = "link" )
+ public String link;
+
+ @XmlElement( name = "description" )
+ public String description;
+
+ @XmlElement( name = "item" )
+ public ArrayList- items = new ArrayList
- ();
+}
diff --git a/vilebot/src/main/java/com/oldterns/vilebot/util/rss/Item.java b/vilebot/src/main/java/com/oldterns/vilebot/util/rss/Item.java
new file mode 100644
index 00000000..62a84d11
--- /dev/null
+++ b/vilebot/src/main/java/com/oldterns/vilebot/util/rss/Item.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.oldterns.vilebot.util.rss;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType( XmlAccessType.FIELD )
+@XmlType( name = "item" )
+public class Item
+{
+ @XmlElement( name = "title" )
+ public String title;
+
+ @XmlElement( name = "link" )
+ public String link;
+
+ @XmlElement( name = "description" )
+ public String description;
+}
diff --git a/vilebot/src/main/java/com/oldterns/vilebot/util/rss/RSS.java b/vilebot/src/main/java/com/oldterns/vilebot/util/rss/RSS.java
new file mode 100644
index 00000000..61ef557f
--- /dev/null
+++ b/vilebot/src/main/java/com/oldterns/vilebot/util/rss/RSS.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.oldterns.vilebot.util.rss;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement( name = "rss" )
+@XmlAccessorType( XmlAccessType.FIELD )
+public class RSS
+{
+ @XmlElement( name = "channel" )
+ public Channel channel;
+
+ @XmlAttribute
+ public String version;
+}