main
An IRC bot that answers random questions, keeps a log from the IRC-chat, easy to integrate in a webpage and montores a phpBB forum for latest topics by loggin in to the forum and checking the RSS-feed.
You need to install additional modules.
Install needed modules in local directory
pip3 install --target modules/ feedparser beautifulsoup4 chardet
Modules in modules/ will be loaded automatically. If you want to use a different directory you can start the program like this instead:
PYTHONPATH=modules python3 main.py
To get help
PYTHONPATH=modules python3 main.py --help
Example of using options
--server=irc.bsnet.se --channel=#db-o-webb --server=irc.bsnet.se --port=6667 --channel=#db-o-webb --nick=marvin --ident=secret
Configuration
Check out the file 'marvin_config_default.json' on how to configure, instead of using cli-options. The default configfile is 'marvin_config.json' but you can change that using cli-options.
Make own actions
Check the file 'marvin_strings.json' for the file where most of the strings are defined and check out 'marvin_actions.py' to see how to write your own actions. Its just a small function.
Read from incoming
Marvin reads messages from the incoming/ directory, if it exists, and writes it out the the irc channel.
1#! /usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4""" 5An IRC bot that answers random questions, keeps a log from the IRC-chat, 6easy to integrate in a webpage and montores a phpBB forum for latest topics 7by loggin in to the forum and checking the RSS-feed. 8 9You need to install additional modules. 10 11# Install needed modules in local directory 12pip3 install --target modules/ feedparser beautifulsoup4 chardet 13 14Modules in modules/ will be loaded automatically. If you want to use a 15different directory you can start the program like this instead: 16 17PYTHONPATH=modules python3 main.py 18 19# To get help 20PYTHONPATH=modules python3 main.py --help 21 22# Example of using options 23--server=irc.bsnet.se --channel=#db-o-webb 24--server=irc.bsnet.se --port=6667 --channel=#db-o-webb 25--nick=marvin --ident=secret 26 27# Configuration 28Check out the file 'marvin_config_default.json' on how to configure, instead 29of using cli-options. The default configfile is 'marvin_config.json' but you 30can change that using cli-options. 31 32# Make own actions 33Check the file 'marvin_strings.json' for the file where most of the strings 34are defined and check out 'marvin_actions.py' to see how to write your own 35actions. Its just a small function. 36 37# Read from incoming 38Marvin reads messages from the incoming/ directory, if it exists, and writes 39it out the the irc channel. 40""" 41 42import argparse 43import json 44import logging 45import logging.config 46import os 47import sys 48 49from discord_bot import DiscordBot 50from irc_bot import IrcBot 51 52import marvin_actions 53import marvin_general_actions 54 55# 56# General stuff about this program 57# 58PROGRAM = "marvin" 59AUTHOR = "Mikael Roos" 60EMAIL = "mikael.t.h.roos@gmail.com" 61VERSION = "0.3.0" 62MSG_VERSION = "{program} version {version}.".format(program=PROGRAM, version=VERSION) 63 64LOG = logging.getLogger("main") 65 66 67def printVersion(): 68 """ 69 Print version information and exit. 70 """ 71 print(MSG_VERSION) 72 sys.exit(0) 73 74 75def mergeOptionsWithConfigFile(options, configFile): 76 """ 77 Read information from config file. 78 """ 79 if os.path.isfile(configFile): 80 with open(configFile, encoding="UTF-8") as f: 81 data = json.load(f) 82 83 options.update(data) 84 res = json.dumps(options, sort_keys=True, indent=4, separators=(',', ': ')) 85 LOG.info("Read configuration from config file '%s'.", configFile) 86 LOG.info("Current configuration is: %s", res) 87 else: 88 LOG.info("Config file '{%s}' is not readable, skipping.", configFile) 89 90 return options 91 92 93def parseOptions(options): 94 """ 95 Merge default options with incoming options and arguments and return them as a dictionary. 96 """ 97 98 parser = argparse.ArgumentParser() 99 parser.add_argument("protocol", choices=["irc", "discord"], nargs="?", default="irc") 100 parser.add_argument("-v", "--version", action="store_true") 101 parser.add_argument("--config") 102 103 for key, value in options.items(): 104 parser.add_argument(f"--{key}", type=type(value)) 105 106 args = vars(parser.parse_args()) 107 if args["version"]: 108 printVersion() 109 if args["config"]: 110 mergeOptionsWithConfigFile(options, args["config"]) 111 112 for parameter in options: 113 if args[parameter]: 114 options[parameter] = args[parameter] 115 116 res = json.dumps(options, sort_keys=True, indent=4, separators=(',', ': ')) 117 LOG.info("Configuration updated after cli options: %s", res) 118 119 return options 120 121 122def determineProtocol(): 123 """Parse the argument to determine what protocol to use""" 124 parser = argparse.ArgumentParser() 125 parser.add_argument("protocol", choices=["irc", "discord"], nargs="?", default="irc") 126 arg, _ = parser.parse_known_args() 127 return arg.protocol 128 129 130def createBot(protocol): 131 """Return an instance of a bot with the requested implementation""" 132 if protocol == "irc": 133 return IrcBot() 134 if protocol == "discord": 135 return DiscordBot() 136 raise ValueError(f"Unsupported protocol: {protocol}") 137 138 139def setupLogging(): 140 """Set up the logging config""" 141 with open("logging.json", encoding="UTF-8") as f: 142 config = json.load(f) 143 logging.config.dictConfig(config) 144 145def main(): 146 """ 147 Main function to carry out the work. 148 """ 149 setupLogging() 150 protocol = determineProtocol() 151 bot = createBot(protocol) 152 options = bot.getConfig() 153 options.update(mergeOptionsWithConfigFile(options, "marvin_config.json")) 154 config = parseOptions(options) 155 bot.setConfig(config) 156 actions = marvin_actions.getAllActions() 157 general_actions = marvin_general_actions.getAllGeneralActions() 158 bot.registerActions(actions) 159 bot.registerGeneralActions(general_actions) 160 bot.begin() 161 162 sys.exit(0) 163 164 165if __name__ == "__main__": 166 main()
68def printVersion(): 69 """ 70 Print version information and exit. 71 """ 72 print(MSG_VERSION) 73 sys.exit(0)
Print version information and exit.
76def mergeOptionsWithConfigFile(options, configFile): 77 """ 78 Read information from config file. 79 """ 80 if os.path.isfile(configFile): 81 with open(configFile, encoding="UTF-8") as f: 82 data = json.load(f) 83 84 options.update(data) 85 res = json.dumps(options, sort_keys=True, indent=4, separators=(',', ': ')) 86 LOG.info("Read configuration from config file '%s'.", configFile) 87 LOG.info("Current configuration is: %s", res) 88 else: 89 LOG.info("Config file '{%s}' is not readable, skipping.", configFile) 90 91 return options
Read information from config file.
94def parseOptions(options): 95 """ 96 Merge default options with incoming options and arguments and return them as a dictionary. 97 """ 98 99 parser = argparse.ArgumentParser() 100 parser.add_argument("protocol", choices=["irc", "discord"], nargs="?", default="irc") 101 parser.add_argument("-v", "--version", action="store_true") 102 parser.add_argument("--config") 103 104 for key, value in options.items(): 105 parser.add_argument(f"--{key}", type=type(value)) 106 107 args = vars(parser.parse_args()) 108 if args["version"]: 109 printVersion() 110 if args["config"]: 111 mergeOptionsWithConfigFile(options, args["config"]) 112 113 for parameter in options: 114 if args[parameter]: 115 options[parameter] = args[parameter] 116 117 res = json.dumps(options, sort_keys=True, indent=4, separators=(',', ': ')) 118 LOG.info("Configuration updated after cli options: %s", res) 119 120 return options
Merge default options with incoming options and arguments and return them as a dictionary.
123def determineProtocol(): 124 """Parse the argument to determine what protocol to use""" 125 parser = argparse.ArgumentParser() 126 parser.add_argument("protocol", choices=["irc", "discord"], nargs="?", default="irc") 127 arg, _ = parser.parse_known_args() 128 return arg.protocol
Parse the argument to determine what protocol to use
131def createBot(protocol): 132 """Return an instance of a bot with the requested implementation""" 133 if protocol == "irc": 134 return IrcBot() 135 if protocol == "discord": 136 return DiscordBot() 137 raise ValueError(f"Unsupported protocol: {protocol}")
Return an instance of a bot with the requested implementation
140def setupLogging(): 141 """Set up the logging config""" 142 with open("logging.json", encoding="UTF-8") as f: 143 config = json.load(f) 144 logging.config.dictConfig(config)
Set up the logging config
146def main(): 147 """ 148 Main function to carry out the work. 149 """ 150 setupLogging() 151 protocol = determineProtocol() 152 bot = createBot(protocol) 153 options = bot.getConfig() 154 options.update(mergeOptionsWithConfigFile(options, "marvin_config.json")) 155 config = parseOptions(options) 156 bot.setConfig(config) 157 actions = marvin_actions.getAllActions() 158 general_actions = marvin_general_actions.getAllGeneralActions() 159 bot.registerActions(actions) 160 bot.registerGeneralActions(general_actions) 161 bot.begin() 162 163 sys.exit(0)
Main function to carry out the work.