This commit is contained in:
Adriene Hutchins 2020-03-23 19:35:41 -04:00
commit aa9e5d95ed
7 changed files with 220 additions and 158 deletions

2
.gitignore vendored
View File

@ -7,6 +7,8 @@ utils/__pycache__/
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
env/
*.pyc
# C extensions # C extensions
*.so *.so

View File

@ -1,114 +0,0 @@
# The default ``config.py``
# flake8: noqa
def set_prefs(prefs):
"""This function is called before opening the project"""
# Specify which files and folders to ignore in the project.
# Changes to ignored resources are not added to the history and
# VCSs. Also they are not returned in `Project.get_files()`.
# Note that ``?`` and ``*`` match all characters but slashes.
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
# '.svn': matches 'pkg/.svn' and all of its children
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
'.hg', '.svn', '_svn', '.git', '.tox']
# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
# ending with ``.py`` are considered to be python files by
# default.
# prefs['python_files'] = ['*.py']
# Custom source folders: By default rope searches the project
# for finding source folders (folders that should be searched
# for finding modules). You can add paths to that list. Note
# that rope guesses project source folders correctly most of the
# time; use this if you have any problems.
# The folders should be relative to project root and use '/' for
# separating folders regardless of the platform rope is running on.
# 'src/my_source_folder' for instance.
# prefs.add('source_folders', 'src')
# You can extend python path for looking up modules
# prefs.add('python_path', '~/python/')
# Should rope save object information or not.
prefs['save_objectdb'] = True
prefs['compress_objectdb'] = False
# If `True`, rope analyzes each module when it is being saved.
prefs['automatic_soa'] = True
# The depth of calls to follow in static object analysis
prefs['soa_followed_calls'] = 0
# If `False` when running modules or unit tests "dynamic object
# analysis" is turned off. This makes them much faster.
prefs['perform_doa'] = True
# Rope can check the validity of its object DB when running.
prefs['validate_objectdb'] = True
# How many undos to hold?
prefs['max_history_items'] = 32
# Shows whether to save history across sessions.
prefs['save_history'] = True
prefs['compress_history'] = False
# Set the number spaces used for indenting. According to
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
# unit-tests use 4 spaces it is more reliable, too.
prefs['indent_size'] = 4
# Builtin and c-extension modules that are allowed to be imported
# and inspected by rope.
prefs['extension_modules'] = []
# Add all standard c-extensions to extension_modules list.
prefs['import_dynload_stdmods'] = True
# If `True` modules with syntax errors are considered to be empty.
# The default value is `False`; When `False` syntax errors raise
# `rope.base.exceptions.ModuleSyntaxError` exception.
prefs['ignore_syntax_errors'] = False
# If `True`, rope ignores unresolvable imports. Otherwise, they
# appear in the importing namespace.
prefs['ignore_bad_imports'] = False
# If `True`, rope will insert new module imports as
# `from <package> import <module>` by default.
prefs['prefer_module_from_imports'] = False
# If `True`, rope will transform a comma list of imports into
# multiple separate import statements when organizing
# imports.
prefs['split_imports'] = False
# If `True`, rope will remove all top-level import statements and
# reinsert them at the top of the module when making changes.
prefs['pull_imports_to_top'] = True
# If `True`, rope will sort imports alphabetically by module name instead
# of alphabetically by import statement, with from imports after normal
# imports.
prefs['sort_imports_alphabetically'] = False
# Location of implementation of
# rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general
# case, you don't have to change this value, unless you're an rope expert.
# Change this value to inject you own implementations of interfaces
# listed in module rope.base.oi.type_hinting.providers.interfaces
# For example, you can add you own providers for Django Models, or disable
# the search type-hinting in a class hierarchy, etc.
prefs['type_hinting_factory'] = (
'rope.base.oi.type_hinting.factory.default_type_hinting_factory')
def project_opened(project):
"""This function is called after opening the project"""
# Do whatever you like here!

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"python.pythonPath": "env\\Scripts\\python3.8.exe"
}

View File

@ -1,43 +1,43 @@
{ {
"VERSION": "1.9 testing", "VERSION": "1.9 testing",
"DESCRIPTION": "a minimalist search utility bot for discord, designed by taciturasa.", "DESCRIPTION": "a minimalist search utility bot for discord, designed by taciturasa.",
"REPO": "https://github.com/taciturasa/searchbot-discord", "REPO": "https://github.com/taciturasa/searchbot-discord",
"SERVER": "https://discord.gg/4BpReNV", "SERVER": "https://discord.gg/4BpReNV",
"TOKEN": "", "TOKEN": "",
"CACHE": false, "CACHE": false,
"PREFIX": ["search!"], "PREFIX": ["search!"],
"MAINTENANCE": false,
"CASE_INSENSITIVE": true,
"PREFIXLESS_DMS": true,
"MENTION_ASSIST": true,
"CUSTOM_HELP": true,
"PERMS": 378944, "MAINTENANCE": false,
"BLOCKED": [], "CASE_INSENSITIVE": true,
"PREFIXLESS_DMS": true,
"BOTLISTS": { "MENTION_ASSIST": true,
"DBL": "", "CUSTOM_HELP": true,
"DBOTS": "",
"BOD": "", "PERMS": 378944,
"DBLCOM": "", "BLOCKED": [],
"BLSPACE": "",
"TABFT_LINK": "", "BOTLISTS": {
"DAD": "" "DBL": "",
}, "DBOTS": "",
"BOD": "",
"HOOKS": { "DBLCOM": "",
"INFO_HOOK": "", "BLSPACE": "",
"WARN_HOOK": "", "TABFT_LINK": "",
"ERROR_HOOK": "", "DAD": ""
"DEBUG_HOOK": "" },
},
"HOOKS": {
"RETHINK": { "INFO_HOOK": "",
"DB": "", "WARN_HOOK": "",
"USERNAME": "", "ERROR_HOOK": "",
"PASSWORD": "", "DEBUG_HOOK": ""
"HOST": "", },
"PORT": null
} "RETHINK": {
} "DB": "",
"USERNAME": "",
"PASSWORD": "",
"HOST": "",
"PORT": null
}
}

View File

@ -9,6 +9,7 @@ import discord
from discord.ext import commands from discord.ext import commands
import aiohttp import aiohttp
import random import random
from urllib import parse
import sys import sys
from typing import List from typing import List
@ -29,7 +30,6 @@ class Search(commands.Cog):
with open('searxes.txt') as f: with open('searxes.txt') as f:
self.instances = f.read().split('\n') self.instances = f.read().split('\n')
async def _search_logic(self, query: str, is_nsfw: bool = False, async def _search_logic(self, query: str, is_nsfw: bool = False,
category: str = None) -> str: category: str = None) -> str:
"""Provides search logic for all search commands.""" """Provides search logic for all search commands."""
@ -280,6 +280,178 @@ class Search(commands.Cog):
) )
await ctx.send(msg) await ctx.send(msg)
@commands.command(aliases=['urban', 'ud'])
async def urbandictionary(self, ctx, *, query: str):
"""Pull data from Urban Dictionary."""
# Handling
async with ctx.typing():
number = 1
if " | " in query:
query, number = query.rsplit(" | ", 1)
search = parse.quote(query)
async with aiohttp.ClientSession() as session:
async with session.get(f"http://api.urbandictionary.com/v0/define?term={search}") as resp:
resp = await resp.json()
if not resp["list"]:
await ctx.send(f"`{query}`` couldn't be found on Urban Dictionary.")
else:
try:
top_result = resp["list"][int(number) - 1]
embed = discord.Embed(title=top_result["word"], description=top_result["definition"][0:425] + "...",
url=top_result["permalink"], color=ctx.author.color)
if top_result["example"]:
embed.add_field(name="Example:",
value=top_result["example"][0:100] + "...", inline=False)
embed.add_field(name="👍", value = top_result["thumbs_up"])
embed.add_field(name="👎", value = top_result["thumbs_down"])
embed.set_author(name=top_result["author"],
icon_url="https://apprecs.org/gp/images/app-icons/300/2f/info.tuohuang.urbandict.jpg")
number = str(int(number) + 1)
embed.set_footer(text=str(len(
resp["list"])) + f" results were found. To see a different result, use {ctx.prefix}ud {query} | {number}.")
try:
await ctx.send(f"**{top_result['word']}** - <{top_result['permalink']}>", embed=embed)
except Exception as e:
await ctx.send(top_result["definition"])
except Exception as e:
print(e)
@commands.command()
async def anime(self, ctx, *, query: str):
"""Lookup anime information online, uses the <https://kitsu.io/> public API."""
base = "https://kitsu.io/api/edge/"
# Handling
async with ctx.typing():
async with aiohttp.ClientSession() as session:
async with session.get(base + "anime", params={"filter[text]": query}) as resp:
resp = await resp.json()
resp = resp['data']
if not resp:
return await ctx.send("The requested anime coudn't be found")
anime = resp[0]
title = f'{anime["attributes"]["canonicalTitle"]}'
anime_id = anime["id"]
url = f"https://kitsu.io/anime/{anime_id}"
thing = '' if not anime['attributes'][
'endDate'] else f' to {anime["attributes"]["endDate"]}'
embed = discord.Embed(
title=f"{title}", color=ctx.author.color, url=url)
embed.description = anime["attributes"]["synopsis"][0:425] + "..."
embed.add_field(name="Average Rating",
value=anime["attributes"]["averageRating"])
embed.add_field(name="Popularity Rank",
value=anime["attributes"]["popularityRank"])
embed.add_field(name="Age Rating",
value=anime["attributes"]["ageRating"])
embed.add_field(
name="Status", value=anime["attributes"]["status"])
embed.add_field(
name="Aired", value=f"{anime['attributes']['startDate']}{thing}")
embed.add_field(name="Episodes",
value=anime['attributes']["episodeCount"])
embed.add_field(
name="Type", value=anime['attributes']["showType"])
embed.set_thumbnail(
url=anime['attributes']["posterImage"]["original"])
embed.set_footer(
text=f"Requested by {ctx.author.name} | Powered by kitsu.io", icon_url=ctx.author.avatar_url_as(format="png"))
try:
await ctx.send(f"**{title}** - <{url}>", embed=embed)
except Exception as e:
aired = f"{anime['attributes']['startDate']}{thing}"
template = f"""
url: {url}
Title: {title}
Average Rating: {anime["attributes"]["averageRating"]}
Popularity Rank: {anime["attributes"]["popularityRank"]}
Age Rating: {anime["attributes"]["ageRating"]}
Status: {anime["attributes"]["status"]}
Aired: {aired}
Type: {anime['attributes']["showType"]}
Powered by kitsu.io"""
await ctx.send(template)
await session.close()
@commands.command()
async def manga(self, ctx, *, query: str):
"""Lookup manga information online, uses the <https://kitsu.io/> public API."""
base = "https://kitsu.io/api/edge/"
# Handling
async with ctx.typing():
async with aiohttp.ClientSession() as session:
async with session.get(base + "manga", params={"filter[text]": query}) as resp:
resp = await resp.json()
resp = resp['data']
if not resp:
return await ctx.send("The requested manga coudn't be found")
manga = resp[0]
title = f'{manga["attributes"]["canonicalTitle"]}'
manga_id = manga["id"]
url = f"https://kitsu.io/manga/{manga_id}"
embed = discord.Embed(
title=f"{title}", color=ctx.author.color, url=url)
embed.description = manga["attributes"]["synopsis"][0:425] + "..."
if manga["attributes"]["averageRating"]:
embed.add_field(name="Average Rating",
value=manga["attributes"]["averageRating"])
embed.add_field(name="Popularity Rank",
value=manga["attributes"]["popularityRank"])
if manga["attributes"]["ageRating"]:
embed.add_field(name="Age Rating",
value=manga["attributes"]["ageRating"])
embed.add_field(
name="Status", value=manga["attributes"]["status"])
thing = '' if not manga['attributes'][
'endDate'] else f' to {manga["attributes"]["endDate"]}'
embed.add_field(
name="Published", value=f"{manga['attributes']['startDate']}{thing}")
if manga['attributes']['chapterCount']:
embed.add_field(name="Chapters",
value=manga['attributes']["chapterCount"])
embed.add_field(
name="Type", value=manga['attributes']["mangaType"])
embed.set_thumbnail(
url=manga['attributes']["posterImage"]["original"])
try:
await ctx.send(f"**{title}** - <{url}>", embed=embed)
except Exception as e:
aired = f"{manga['attributes']['startDate']}{thing}"
template = f"""
url: {url}
Title: {title}
Average Rating: {manga["attributes"]["averageRating"]}
Popularity Rank: {manga["attributes"]["popularityRank"]}
Age Rating: {manga["attributes"]["ageRating"]}
Status: {manga["attributes"]["status"]}
Aired: {aired}
Type: {manga['attributes']["showType"]}
Powered by kitsu.io"""
await ctx.send(template)
await session.close()
@commands.command() @commands.command()
@commands.is_owner() @commands.is_owner()
async def rejson(self, ctx): async def rejson(self, ctx):
@ -332,7 +504,6 @@ class Search(commands.Cog):
name="Search Results" name="Search Results"
) )
# Sends result # Sends result
await ctx.send(msg) await ctx.send(msg)

View File

@ -129,7 +129,7 @@ class Logging():
async def error(self, error: Exception, ctx: Context, name: Optional[str]): async def error(self, error: Exception, ctx: Context, name: Optional[str]):
"""Logs errors and sends them to the appropriate places.""" """Logs errors and sends them to the appropriate places."""
# Prerequisites # Prerequisites
error_embed = await self._create_error_embed(error, ctx) error_embed = await self._create_error_embed(error, ctx)