Better websearch. Readded reddit to bot commands

This commit is contained in:
Remy Moll 2021-02-18 17:24:23 +01:00
parent 20a8cb70e1
commit 3ec1744a15
11 changed files with 351 additions and 87 deletions

View File

@ -1,4 +1,5 @@
from . import google
from . import keys
from . import reddit
from . import weather
from . import reddit
from . import search

View File

@ -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 <b>" + param_string.replace("+"," ") + "</b>:\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

View File

@ -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 += "<b>" + submission.title + "</b>" + "\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 += "<b>" + submission.title + "</b>" + "\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 []

21
bot2/api/search.py Normal file
View File

@ -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!

View File

@ -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

View File

@ -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."""

177
bot2/commands/reddit.py Normal file
View File

@ -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 += "<b>" + j["title"] + "</b> \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 += "<b>" + j["title"] + "</b> \n" + j["content"] + "\n\n"
# if message == "":
# message += "Could not fetch news."
# query.edit_message_text(news, paresemode=ParseMode.HTML)
# return ConversationHandler.END

58
bot2/commands/search.py Normal file
View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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()