Advertisement
Toude

LazyFactorian

Apr 12th, 2019
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.58 KB | None | 0 0
  1. import discord
  2. from discord.ext import commands
  3. from discord.utils import find as dfind
  4. import math
  5. import requests as rq
  6. from bs4 import BeautifulSoup
  7. import logging
  8.  
  9. TOKEN = "your_token"
  10. PREFIX = "f:"
  11. FACTORIO_MOD_BASE_URL = "https://mods.factorio.com/mod/"
  12. FACTORIO_MOD_SEARCH_BASE_URL = "https://mods.factorio.com/query/"
  13. FACTORIO_WIKI_BASE_URL = "https://wiki.factorio.com/"
  14. FACTORIO_WIKI_SEARCH_BASE_URL = ""
  15. FACTORIO_WIKI_BASE_IMG_URL = "https://wiki.factorio.com/images/"
  16.  
  17. USER_AGENT= {'User-Agent': 'Mozilla/5.0'}
  18.  
  19. #only takes msgs starting with PREFIX as commands
  20. bot = commands.Bot(command_prefix=PREFIX)
  21.  
  22. logger = logging.getLogger("discord")
  23. logger.setLevel(logging.INFO)
  24.  
  25. handler = logging.FileHandler(filename="discord.log", encoding="utf-8", mode="w")
  26. handler.setFormatter(logging.Formatter('''%(asctime)s:%(levelname)s:%(name)s:\t%(message)s'''))
  27. logger.addHandler(handler)
  28.  
  29.  
  30.  
  31. #Checks
  32. def is_author():
  33.     def check_condition(ctx):
  34.         return ctx.message.author.id ==289426079544901633
  35.     return commands.check(check_condition)
  36.  
  37.  
  38.  
  39. @bot.event
  40. async def on_ready():
  41.     print('We have logged in as {0.user}'.format(bot))
  42.  
  43. @bot.event
  44. async def on_message(message):
  45.     if message.author == bot.user:
  46.         return
  47.  
  48.     if message.content.startswith('$$abs_test'):
  49.         await message.channel.send('Hello!')
  50.    
  51.     await bot.process_commands(message)
  52.  
  53.  
  54. @bot.command()
  55. async def ping(ctx):
  56.     '''This command responds with the current latency. Also this docstring is automagically turned into the output of the help command'''
  57.     latency = bot.latency #included in the API
  58.     #send replies to the message received. This means in the same channel.
  59.     await ctx.send("Latency of {} seconds".format(latency))
  60.  
  61.  
  62. @bot.group(pass_context=True)
  63. async def mod(ctx):
  64.     '''a suite of commands about Factorio mods'''
  65.     if ctx.invoked_subcommand is None:
  66.         await ctx.send("Couldn't parse command: Not Enough Arguments")
  67.  
  68.  
  69. @mod.command(pass_context=True)
  70. async def info(ctx, mod_name):
  71.     '''Gives some basic info about any mod avaialble on the mod portal
  72.     you must give the raw name of the mod in order for the bot to find the actual page. If you don't know the mod's raw name search it up with the "search" subcommand.'''
  73.     fields = mod_scrapper(str(mod_name).replace(" ", "-"))
  74.     print(fields)
  75.     embed = discord.Embed(
  76.         title = mod_name,
  77.         description = None,
  78.         colour = discord.Colour.from_rgb(228, 141, 36),
  79.         url = fields[-1]
  80.         )
  81.     embed.set_footer(text="Made with love by Toude#6601")
  82.     #embed.set_image(url="")
  83.     embed.set_thumbnail(url=fields[5])
  84. #   embed.set_author(name="Toude#6601")
  85.    
  86.     embed.add_field(name="Updated", value=fields[0], inline=True)
  87.     embed.add_field(name="Compatibility", value=fields[1], inline=True)
  88.     embed.add_field(name="Downloads", value=fields[2], inline=True)
  89.     embed.add_field(name="Author", value=fields[4], inline=True)
  90.     embed.add_field(name="Description", value=fields[3], inline=True)
  91.  
  92.     await ctx.send(embed=embed)
  93.  
  94. def mod_scrapper(mod_name):
  95.     full_url = FACTORIO_MOD_BASE_URL + mod_name
  96.     html_page =rq.get(full_url, headers = USER_AGENT)
  97.     soup = BeautifulSoup(html_page.content, "html.parser")
  98.  
  99.     fields = []
  100.     for field in soup.findAll("div", {"class":"mod-card-info-tag-label"}):
  101.         #print(field.get_text())
  102.         fields.append(str(field.get_text()))
  103.     assert len(fields)==3, "found {} fields instead of 3".format(len(fields))
  104.  
  105.     for field in soup.findAll("div", {"class": "mod-card-summary"}):
  106.         fields.append(str(field.get_text()))
  107.     assert len(fields)==4, "found {} fields instead of 4".format(len(fields))
  108.  
  109.     for field in soup.findAll("div", {"class": "mod-card-author"}):
  110.         fields.append(field.get_text().split(" ")[1])
  111.  
  112.     tmp = []
  113.     for field in soup.findAll("img"):
  114.         tmp.append(field.get("src"))
  115.     if len(tmp)>0:
  116.         fields.append(tmp[0])
  117.     else:
  118.         print("No thumbnail available for {}".format(full_url))
  119.  
  120.     fields.append(full_url)
  121.     return fields
  122.  
  123.  
  124. @mod.command(pass_context=True)
  125. async def search(ctx, query):
  126.     '''allows you to browse the mod protal from Discord. Outputs the name and the raw name of the top 6 mods matching the query.'''
  127.     query_list = query.split(" ")
  128.     query_str = ""
  129.     for q in query_list:
  130.         query_str = query_str + "+{}".format(q)
  131.  
  132.     full_url = str(FACTORIO_MOD_SEARCH_BASE_URL+query_str)
  133.     results, result_urls = mod_search(full_url)
  134.  
  135.     print(results, result_urls)
  136.     embed = discord.Embed(
  137.         title = "{} result for {}".format(len(results), query),
  138.         description = None,
  139.         colour = discord.Colour.from_rgb(228, 141, 36),
  140.         url = full_url
  141.         )
  142.  
  143.     if len(results)>6:
  144.         results = results[:6]
  145.         result_urls = result_urls[:6]
  146.     i =0
  147.     for result in results:
  148.         i+=1
  149.         embed.add_field(name="#{}\t{}".format(i, result), value="{}".format(FACTORIO_MOD_BASE_URL+result_urls[i-1]) , inline=False)
  150.     embed.set_footer(text="Made with love by Toude#6601")
  151.    
  152.     await ctx.send(embed=embed)
  153.  
  154. def mod_search(query):
  155.     html_page = rq.get(query, headers=USER_AGENT)
  156.     soup = BeautifulSoup(html_page.content, "html.parser")
  157.     #print(soup.prettify())
  158.     results = []
  159.     result_urls = []
  160.  
  161.     for field in soup.findAll("h2", {"class": "mod-card-title"}):
  162.         mod_name = field.get_text().strip()
  163.         results.append(mod_name)
  164.  
  165.     for field in soup.findAll("h2", {"class": "mod-card-title"}):
  166.         mod_url = field.find("a")
  167.         mod_url = mod_url.get("href").split("/")[-1]
  168.         result_urls.append(mod_url)
  169.  
  170.     return results, result_urls
  171.  
  172.  
  173. @bot.group(pass_context=True)
  174. async def wiki(ctx):
  175.     '''A tool which allows you to browse factorio wiki directly from Discord'''
  176.     if ctx.invoked_subcommand is None:
  177.         await ctx.send("Couldn't parse {} command: Not Enough Arguments".format(ctx.invoked_subcommand))
  178.  
  179. @wiki.command(pass_context=True)
  180. async def search(ctx, language="en"):
  181.     '''allows you to search the wiki. Language can be any 2-letters country code. Will return "Error: Page not available in specified language" if the page does not exists in this language but in others'''
  182.     pass
  183.  
  184. @wiki.command(pass_context=True)
  185. async def info(ctx, query):
  186.     '''command meant to give basic information about a factorio element with a wiki entry'''
  187.     if type(query)!=str:
  188.         await ctx.send('''Argument Error: query provided isn't a string, try quoting your query like this "query".''')
  189.  
  190.     fields = wiki_scrapper(query)
  191.  
  192.     embed = discord.Embed(
  193.         title = fields[0],
  194.         description = None,
  195.         colour = discord.Colour.from_rgb(228, 141, 36),
  196.         url = fields[1]
  197.         )
  198.     embed.set_footer(text="Made with love by Toude#6601")
  199.     if fields[2]!=None:
  200.         embed.set_thumbnail(url=fields[2])
  201.     embed.add_field(name="Description", value=fields[3], inline=True)
  202.  
  203.     await ctx.send(embed=embed)
  204.  
  205.  
  206.  
  207.  
  208. def wiki_scrapper(query):
  209.     fields = []
  210.     fields.append(query.capitalize())
  211.     title = fields[0].replace(" ", "_")
  212.     local_url = FACTORIO_WIKI_BASE_URL+ title
  213.     image_url = check_thumbnail(FACTORIO_WIKI_BASE_IMG_URL+title+".png")
  214.  
  215.     fields.append(local_url)
  216.     fields.append(image_url)
  217.  
  218.     html_page =rq.get(local_url, headers = USER_AGENT)
  219.     soup = BeautifulSoup(html_page.content, "html.parser")
  220.    
  221.     for field in soup.findAll("meta", {"name": "description"}):
  222.         fields.append(field["content"])
  223.  
  224.     return fields
  225.  
  226. def check_thumbnail(url):
  227.     img_page = rq.get(url, headers=USER_AGENT)
  228.     soup = BeautifulSoup(img_page.content, "html.parser")
  229.  
  230.     for field in soup.findAll("div", {"class": "mw-content-ltr"}):
  231.         if field.get_text().find("There is currently no text in this page.")!=(-1):
  232.             return None
  233.     return url
  234.  
  235.  
  236. @bot.command()
  237. @is_author()
  238. async def shutdown(ctx):
  239.     print("Goodbye")
  240.     await bot.change_presence(status=discord.Status.offline)
  241.     #time.sleep(0.1)
  242.     await ctx.send("Goodbye")
  243.     await bot.close()
  244.     await quit()
  245.  
  246.  
  247. bot.run(TOKEN)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement