diff --git a/bot2/api/__init__.py b/bot2/api/__init__.py
index 924f953..d5f9e9b 100644
--- a/bot2/api/__init__.py
+++ b/bot2/api/__init__.py
@@ -1,4 +1,5 @@
-from . import google
from . import keys
from . import reddit
-from . import weather
\ No newline at end of file
+from . import weather
+from . import reddit
+from . import search
\ No newline at end of file
diff --git a/bot2/api/google.py b/bot2/api/google.py
deleted file mode 100644
index 2ff701c..0000000
--- a/bot2/api/google.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import googlesearch
-
-
-def query(params):
- param_string = ""
- for word in params:
- param_string += word + "+"
- param_string = param_string[:-1]
- search_url = "https://google.com/search?q=" + param_string
-
- try:
- res = googlesearch.search(param_string.replace("+"," ") ,num=5,start=0,stop=5)
- send_string = "Results for " + param_string.replace("+"," ") + ":\n\n"
- for url in res:
- send_string += url + "\n\n"
- send_string += "Search url:\n" + search_url
- except:
- send_string = "Search url:\n" + search_url
-
- return send_string
diff --git a/bot2/api/reddit.py b/bot2/api/reddit.py
index 49ee0d3..2cd5112 100644
--- a/bot2/api/reddit.py
+++ b/bot2/api/reddit.py
@@ -1,50 +1,56 @@
import praw
-try:
- import bot.api.keys as keys
-except:
- import keys
-
-stream = praw.Reddit(client_id = keys.reddit_id, client_secret = keys.reddit_secret, user_agent=keys.reddit_user_agent)
-
-def get_top(subreddit, number, return_type="text"):
- if return_type == "text":
- message = ""
- try:
- for submission in stream.subreddit(subreddit).top(limit=number):
- if not submission.stickied:
- message += "" + submission.title + "" + "\n" + submission.selftext + "\n\n\n"
- return message
- except:
- return "Api call failed, sorry"
- else:
- images = []
- try:
- for submission in stream.subreddit(subreddit).top(limit=number):
- if not submission.stickied:
- t = {"image": submission.url, "caption": submission.title}
- images.append(t)
- return images
- except:
- return ["Api call failed, sorry"]
-def get_random_rising(subreddit, number, return_type="text"):
- if return_type == "text":
- message = ""
- try:
- for submission in stream.subreddit(subreddit).random_rising(limit=number):
- if not submission.stickied:
- message += "" + submission.title + "" + "\n" + submission.selftext + "\n\n\n"
- return message
- except:
- return "Api call failed, sorry"
- else:
- images = []
- try:
- for submission in stream.subreddit(subreddit).random_rising(limit=number):
- if not submission.stickied:
- t = {"image": submission.url, "caption": submission.title}
- images.append(t)
- return images
- except:
- return ["Api call failed, sorry"]
+
+class RedditFetch():
+ def __init__(self, key):
+ self.stream = praw.Reddit(client_id = key["id"], client_secret = key["secret"], user_agent=key["user_agent"])
+
+ def get_top(self, subreddit, number, return_type="text"):
+ if return_type == "text":
+ posts = []
+ try:
+ for submission in self.stream.subreddit(subreddit).top(limit=number):
+ p = {}
+ if not submission.stickied:
+ p["title"] = submission.title
+ p["content"] = submission.selftext
+ posts.append(p)
+ return posts
+ except:
+ return []
+ else:
+ images = []
+ try:
+ for submission in self.stream.subreddit(subreddit).top(limit=number):
+ if not submission.stickied:
+ t = {"image": submission.url, "caption": submission.title}
+ images.append(t)
+ return images
+ except:
+ return []
+
+
+ def get_random_rising(self, subreddit, number, return_type="text"):
+ if return_type == "text":
+ posts = []
+ try:
+ for submission in self.stream.subreddit(subreddit).random_rising(limit=number):
+ p = {}
+ if not submission.stickied:
+ p["title"] = submission.title
+ p["content"] = submission.selftext
+ posts.append(p)
+ return posts
+ except:
+ return []
+ else:
+ images = []
+ try:
+ for submission in self.stream.subreddit(subreddit).random_rising(limit=number):
+ if not submission.stickied:
+ t = {"image": submission.url, "caption": submission.title}
+ images.append(t)
+ return images
+ except:
+ return []
diff --git a/bot2/api/search.py b/bot2/api/search.py
new file mode 100644
index 0000000..adf1ee6
--- /dev/null
+++ b/bot2/api/search.py
@@ -0,0 +1,21 @@
+import duckduckpy
+
+class WebSearch():
+ def __init__(self):
+ self.search = duckduckpy.query
+
+ def get_result(self, query):
+ try:
+ res = []
+ response = self.search(query, container = "dict")["related_topics"]
+ for r in response:
+ if "text" in r:
+ res.append({
+ "text" : r["text"],
+ "url": r["first_url"]
+ })
+ except:
+ res = ["Connection error"]
+ return res
+
+# TODO: this api has more potential. Extract images or quick facts!
\ No newline at end of file
diff --git a/bot2/commands/__init__.py b/bot2/commands/__init__.py
index 561818f..7483e3d 100644
--- a/bot2/commands/__init__.py
+++ b/bot2/commands/__init__.py
@@ -1,2 +1,2 @@
# Placeholder
-from . import clock, help, weather, status, zvv, lists, alias, plaintext
+from . import clock, help, weather, status, zvv, lists, alias, plaintext, reddit, search
diff --git a/bot2/commands/help.py b/bot2/commands/help.py
index 4597cec..4ed8646 100644
--- a/bot2/commands/help.py
+++ b/bot2/commands/help.py
@@ -1,6 +1,6 @@
from .template import *
-FIRST = 1
+FIRST, EXECUTE = range(2)
class Help(BotFunc):
@@ -20,6 +20,7 @@ class Help(BotFunc):
CallbackQueryHandler(self.choose_specific, pattern="^specific$"),
CallbackQueryHandler(self.print_one, pattern='func-'),
],
+ EXECUTE :[CallbackQueryHandler(self.execute_now)],
# ConversationHandler.TIMEOUT : [
# CallbackQueryHandler(self.timeout)
# ]
@@ -46,7 +47,10 @@ class Help(BotFunc):
]
]
reply_markup = InlineKeyboardMarkup(keyboard)
- update.message.reply_text("What exactly do you want?", reply_markup=reply_markup)
+ if update.message:
+ update.message.reply_text("What exactly do you want?", reply_markup=reply_markup)
+ else:
+ update._effective_chat.send_message("What exactly do you want?", reply_markup=reply_markup)
return FIRST
@@ -82,13 +86,28 @@ class Help(BotFunc):
query.answer()
message = name + ": `" + self.available_commands[name] + "`"
+
+ keyboard = [[InlineKeyboardButton("Call " + name + " now", callback_data=name),]]
+ reply_markup = InlineKeyboardMarkup(keyboard)
+
query.edit_message_text(
text= message,
+ #reply_markup = reply_markup,
parse_mode = ParseMode.MARKDOWN_V2
)
- return ConversationHandler.END
-
+ return ConversationHandler.END #EXECUTE
+ def execute_now(self, update: Update, context: CallbackContext) -> None:
+ query = update.callback_query
+ name = query.data
+ query.answer()
+ funcs = context.dispatcher.handlers[0]
+ for func in funcs:
+ if name == func.entry_points[0].command[0]:
+ break
+ callback = func.entry_points[0].callback
+ func.callback(update, context)
+ return FIRST
def timeout(self, update: Update, context: CallbackContext) -> None:
"""For dying conversation. Currently unused."""
diff --git a/bot2/commands/reddit.py b/bot2/commands/reddit.py
new file mode 100644
index 0000000..bfaadeb
--- /dev/null
+++ b/bot2/commands/reddit.py
@@ -0,0 +1,177 @@
+from .template import *
+
+
+CHOOSE_NUM = 1
+class Joke(BotFunc):
+ """Tells a joke from reddit."""
+
+ def __init__(self, api, prst):
+ super().__init__(prst)
+ self.available_commands = {}
+ self.api = api
+
+
+ def create_handler(self):
+ conv_handler = ConversationHandler(
+ entry_points=[CommandHandler('joke', self.entry_point)],
+ states={
+ CHOOSE_NUM: [CallbackQueryHandler(self.get_jokes),],
+ },
+ fallbacks=[CommandHandler('joke', self.entry_point)],
+ # conversation_timeout=5,
+ )
+ return conv_handler
+
+
+ def entry_point(self, update: Update, context: CallbackContext) -> None:
+ super().entry_point()
+ keyboard = [[InlineKeyboardButton(str(i), callback_data=str(i)) for i in range(1,11)]]
+ reply_markup = InlineKeyboardMarkup(keyboard)
+ update.message.reply_text("How many jokes?", reply_markup=reply_markup)
+ return CHOOSE_NUM
+
+
+ def get_jokes(self, update: Update, context: CallbackContext) -> None:
+ query = update.callback_query
+ number = int(query.data)
+ query.answer()
+ jokes = self.api.get_random_rising("jokes", number, "text")
+ # formating
+ message = ""
+ for j in jokes:
+ message += "" + j["title"] + " \n" + j["content"] + "\n\n"
+ if message == "":
+ message += "Could not fetch jokes."
+ query.edit_message_text(text = message, parse_mode = ParseMode.HTML)
+ return ConversationHandler.END
+
+
+
+
+CHOOSE_TOPIC = 0
+class Meme(BotFunc):
+ """Gets the latest memes from reddit"""
+
+ def __init__(self, api, prst):
+ super().__init__(prst)
+ self.available_commands = {}
+ self.api = api
+
+
+ def create_handler(self):
+ conv_handler = ConversationHandler(
+ entry_points=[CommandHandler('meme', self.entry_point)],
+ states={
+ CHOOSE_TOPIC: [CallbackQueryHandler(self.choose_topic)],
+ CHOOSE_NUM :[CallbackQueryHandler(self.get_memes)],
+ },
+ fallbacks=[CommandHandler('meme', self.entry_point)],
+ )
+ return conv_handler
+
+
+ def entry_point(self, update: Update, context: CallbackContext) -> None:
+ super().entry_point()
+
+ keyboard = [
+ [InlineKeyboardButton("General", callback_data="memes"),],
+ [InlineKeyboardButton("Dank memes", callback_data="dankmemes"),],
+ [InlineKeyboardButton("Maths", callback_data="mathmemes"),],
+ [InlineKeyboardButton("Physics", callback_data="physicsmemes"),],
+ [InlineKeyboardButton("Biology", callback_data="biologymemes"),],
+ ]
+ reply_markup = InlineKeyboardMarkup(keyboard)
+ update.message.reply_text("What kind of memes?", reply_markup=reply_markup)
+ return CHOOSE_TOPIC
+
+
+ def choose_topic(self, update: Update, context: CallbackContext) -> None:
+ super().entry_point()
+ query = update.callback_query
+ d = query.data
+ query.answer()
+
+ keyboard = [[InlineKeyboardButton(str(i), callback_data=d + "-" + str(i)) for i in range(1,11)]]
+ reply_markup = InlineKeyboardMarkup(keyboard)
+ query.edit_message_text("How many memes?", reply_markup=reply_markup)
+ return CHOOSE_NUM
+
+
+ def get_memes(self, update: Update, context: CallbackContext) -> None:
+ query = update.callback_query
+ data = query.data.split("-")
+ query.answer()
+
+ memes = self.api.get_random_rising(data[0], int(data[1]), "photo")
+ if len(memes) != 0:
+ for m in memes:
+ update.effective_chat.send_photo(photo = m["image"],caption = m["caption"])
+ else:
+ update.effective_chat.send_message("Sorry, the meme won't yeet.")
+ return ConversationHandler.END
+
+
+
+
+# class News(BotFunc):
+# """Gets the latest news from reddit"""
+
+# def __init__(self, api, prst):
+# super().__init__(prst)
+# self.available_commands = {}
+# self.api = api
+
+
+# def create_handler(self):
+# conv_handler = ConversationHandler(
+# entry_points=[CommandHandler('news', self.entry_point)],
+# states={
+# CHOOSE_TOPIC: [CallbackQueryHandler(self.choose_topic)],
+# CHOOSE_NUM :[CallbackQueryHandler(self.get_news)],
+# },
+# fallbacks=[CommandHandler('news', self.entry_point)],
+# )
+# return conv_handler
+
+
+# def entry_point(self, update: Update, context: CallbackContext) -> None:
+# super().entry_point()
+
+# keyboard = [
+# [InlineKeyboardButton("World", callback_data="worldnews"),],
+# [InlineKeyboardButton("Germany", callback_data="germannews"),],
+# [InlineKeyboardButton("France", callback_data="francenews"),],
+# [InlineKeyboardButton("Europe", callback_data="eunews"),],
+# [InlineKeyboardButton("USA", callback_data="usanews"),],
+# ]
+# reply_markup = InlineKeyboardMarkup(keyboard)
+# update.message.reply_text("What kind of news?", reply_markup=reply_markup)
+# return CHOOSE_TOPIC
+
+
+# def choose_topic(self, update: Update, context: CallbackContext) -> None:
+# super().entry_point()
+# query = update.callback_query
+# d = query.data
+# query.answer()
+
+# keyboard = [[InlineKeyboardButton(str(i), callback_data=d + "-" + str(i)) for i in range(1,11)]]
+# reply_markup = InlineKeyboardMarkup(keyboard)
+# query.edit_message_text("How many entries?", reply_markup=reply_markup)
+# return CHOOSE_NUM
+
+
+# def get_news(self, update: Update, context: CallbackContext) -> None:
+# query = update.callback_query
+# data = query.data.split("-")
+# query.answer()
+# #try:
+# news = self.api.get_top(data[0], data[1], "text")
+# # formating
+# message = ""
+# for j in news:
+# message += "" + j["title"] + " \n" + j["content"] + "\n\n"
+# if message == "":
+# message += "Could not fetch news."
+# query.edit_message_text(news, paresemode=ParseMode.HTML)
+# return ConversationHandler.END
\ No newline at end of file
diff --git a/bot2/commands/search.py b/bot2/commands/search.py
new file mode 100644
index 0000000..c8a679c
--- /dev/null
+++ b/bot2/commands/search.py
@@ -0,0 +1,58 @@
+from .template import *
+
+
+SEARCH, MORE = range(2)
+class Search(BotFunc):
+ """Browse the web for a topic."""
+
+ def __init__(self, api, prst):
+ super().__init__(prst)
+ self.available_commands = {}
+ self.api = api
+
+
+ def create_handler(self):
+ conv_handler = ConversationHandler(
+ entry_points=[CommandHandler('search', self.entry_point)],
+ states={
+ SEARCH: [MessageHandler(Filters.text, self.get_results),],
+ MORE: [CallbackQueryHandler(self.show_more, pattern="^more$"),],
+ },
+ fallbacks=[CommandHandler('search', self.entry_point)],
+ conversation_timeout=20,
+ )
+ return conv_handler
+
+
+ def entry_point(self, update: Update, context: CallbackContext) -> None:
+ super().entry_point()
+
+ update.message.reply_text("What are we searching?")
+ return SEARCH
+
+
+ def get_results(self, update: Update, context: CallbackContext) -> None:
+ search = update.message.text
+ results = self.api.get_result(search)
+ keyboard = [[InlineKeyboardButton("More!", callback_data="more")]]
+ reply_markup = InlineKeyboardMarkup(keyboard)
+
+ # formating
+ self.results = results
+ first = results[0]
+ message = first["text"] + "\n(" + first["url"] + ")\n"
+
+ update.message.reply_text(text = message, reply_markup=reply_markup)
+ return MORE
+
+
+ def show_more(self, update: Update, context: CallbackContext) -> None:
+ query = update.callback_query
+ query.answer()
+
+ message = ""
+ for r in self.results:
+ message += r["text"] + "\n(" + r["url"] + ")\n"
+
+ query.edit_message_text(message)
+ return ConversationHandler.END
\ No newline at end of file
diff --git a/bot2/commands/status.py b/bot2/commands/status.py
index 03ac9bd..c762414 100644
--- a/bot2/commands/status.py
+++ b/bot2/commands/status.py
@@ -34,7 +34,6 @@ class Status(BotFunc):
def entry_point(self, update: Update, context: CallbackContext) -> None:
super().entry_point()
- user = update.message.from_user
keyboard = [
[
InlineKeyboardButton("And the log?", callback_data="full"),
@@ -72,7 +71,10 @@ class Status(BotFunc):
tot_e = np.array(self.persistence["bot"]["execute_activity"]["count"]).sum()
message += "Commands executed `" + str(tot_e) + "`\n"
- update.message.reply_text(message, reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN)
+ if update.message:
+ update.message.reply_text(message, reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN)
+ else:
+ update._effective_chat.send_message(message, reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN)
return FIRST
diff --git a/bot2/main.py b/bot2/main.py
index 932d958..95c1812 100644
--- a/bot2/main.py
+++ b/bot2/main.py
@@ -21,7 +21,8 @@ class ChatBot():
self.persistence = prst
# Import submodules
self.api_weather = api.weather.WeatherFetch(api.keys.weather_api)
- # self.reddit_api = api.reddit.RedditFetch()
+ self.api_reddit = api.reddit.RedditFetch(api.keys.reddit_api)
+ self.api_search = api.search.WebSearch()
# and so on
self.telegram = Updater(api.keys.telegram_api, use_context=True)
@@ -37,17 +38,15 @@ class ChatBot():
"status" : self.commands.status.Status(name, version, prst),
"zvv" : self.commands.zvv.Zvv(prst),
"list" : self.commands.lists.Lists(prst),
- #"alias" : commands.alias.Alias(self.dispatcher, prst),
+ # "alias" : commands.alias.Alias(self.dispatcher, prst),
+ "joke" : self.commands.reddit.Joke(self.api_reddit, prst),
+ "meme" : self.commands.reddit.Meme(self.api_reddit, prst),
+ # "news" : self.commands.reddit.News(self.api_reddit, prst),
+ "search" : self.commands.search.Search(self.api_search, prst),
+
+
"plaintext" : self.commands.plaintext.Plain(prst) # for handling non-command messages that should simply contribute to statistics
}
-
- # "events" : self.bot_print_events,
- # "wikipedia" : self.bot_show_wikipedia,
- # "cronjob" : self.bot_cronjob,
- # "joke" : self.bot_tell_joke,
- # "meme" : self.bot_send_meme,
- # "news" : self.bot_send_news,
- # }
# must be a class that has a method create_handler
def add_commands(self):
diff --git a/launcher.py b/launcher.py
index 195e8c2..d7bdd72 100644
--- a/launcher.py
+++ b/launcher.py
@@ -41,12 +41,13 @@ class Launcher():
self.dashboard_module = dashboard.main.DashBoard(host_ip="0.0.0.0", prst=self.persistence)
self.modules = {
- "clock" : self.clock_module,
"bot" : self.bot_module,
+ "clock" : self.clock_module,
"dashboard" : self.dashboard_module,
}
for module in self.modules.values():
+ self.logger.info("Starting module "+ module.__class__.__name__)
module.modules = self.modules
module.start()