Better websearch. Readded reddit to bot commands
This commit is contained in:
		| @@ -1,4 +1,5 @@ | ||||
| from . import google | ||||
| from . import keys | ||||
| from . import reddit | ||||
| from . import weather | ||||
| from . import reddit | ||||
| from . import search | ||||
| @@ -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 | ||||
| @@ -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
									
								
							
							
						
						
									
										21
									
								
								bot2/api/search.py
									
									
									
									
									
										Normal 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! | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										177
									
								
								bot2/commands/reddit.py
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										58
									
								
								bot2/commands/search.py
									
									
									
									
									
										Normal 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 | ||||
| @@ -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 | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										19
									
								
								bot2/main.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								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): | ||||
|   | ||||
| @@ -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() | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Remy Moll
					Remy Moll