Math & Fix Gamecodes

This commit is contained in:
Nicba1010
2018-02-05 00:05:50 +01:00
parent 2462201ea2
commit bcbd97027c
2 changed files with 278 additions and 140 deletions

290
bot.py
View File

@@ -11,210 +11,220 @@ from discord.ext.commands import Bot
from api import newline_separator, directions, regions, statuses, release_types
from api.request import ApiRequest
from bot_config import latest_limit, newest_header, invalid_command_text, oldest_header, boot_up_message
from math_parse import NumericStringParser
from utils import limit_int
channel_id = "291679908067803136"
bot_spam_id = "319224795785068545"
rpcs3Bot = Bot(command_prefix="!")
pattern = '[A-z]{4}\\d{5}'
nsp = NumericStringParser()
@rpcs3Bot.event
async def on_message(message: Message):
"""
OnMessage event listener
:param message: message
"""
if message.author.name == "RPCS3 Bot":
return
try:
if message.content[0] == "!":
return await rpcs3Bot.process_commands(message)
except IndexError as ie:
print(message.content)
return
codelist = []
for matcher in re.finditer(pattern, message.content):
code = str(matcher.group(0)).upper()
if code not in codelist:
codelist.append(code)
print(code)
for code in codelist:
info = await get_code(code)
if not info == "None":
await rpcs3Bot.send_message(message.channel, info)
"""
OnMessage event listener
:param message: message
"""
if message.author.name == "RPCS3 Bot":
return
try:
if message.content[0] == "!":
return await rpcs3Bot.process_commands(message)
except IndexError as ie:
print(message.content)
return
codelist = []
for matcher in re.finditer(pattern, message.content):
code = str(matcher.group(0)).upper()
if code not in codelist:
codelist.append(code)
print(code)
for code in codelist:
info = await get_code(code)
if not info == "None":
await rpcs3Bot.send_message(message.channel, info)
@rpcs3Bot.command()
async def math(*args):
"""Math, here you go Juhn"""
return await rpcs3Bot.say(nsp.eval(''.join(map(str, args))))
@rpcs3Bot.command()
async def credits(*args):
"""Author Credit"""
return await rpcs3Bot.say("```\nMade by Roberto Anic Banic aka nicba1010!\n```")
"""Author Credit"""
return await rpcs3Bot.say("```\nMade by Roberto Anic Banic aka nicba1010!\n```")
# noinspection PyMissingTypeHints
@rpcs3Bot.command(pass_context=True)
async def c(ctx, *args):
"""Searches the compatibility database, USE: !c searchterm """
await compat_search(ctx, *args)
"""Searches the compatibility database, USE: !c searchterm """
await compat_search(ctx, *args)
# noinspection PyMissingTypeHints
@rpcs3Bot.command(pass_context=True)
async def compat(ctx, *args):
"""Searches the compatibility database, USE: !compat searchterm"""
await compat_search(ctx, *args)
"""Searches the compatibility database, USE: !compat searchterm"""
await compat_search(ctx, *args)
# noinspection PyMissingTypeHints,PyMissingOrEmptyDocstring
async def compat_search(ctx, *args):
search_string = ""
for arg in args:
search_string += (" " + arg) if len(search_string) > 0 else arg
search_string = ""
for arg in args:
search_string += (" " + arg) if len(search_string) > 0 else arg
request = ApiRequest(ctx.message.author).set_search(search_string)
response = request.request()
await dispatch_message(response.to_string())
request = ApiRequest(ctx.message.author).set_search(search_string)
response = request.request()
await dispatch_message(response.to_string())
# noinspection PyMissingTypeHints
@rpcs3Bot.command(pass_context=True)
async def top(ctx, *args):
"""
Gets the x (default 10) top oldest/newest updated games
Example usage:
!top old 10
!top new 10 jap
!top old 10 all
!top new 10 jap playable
!top new 10 jap playable bluray
!top new 10 jap loadable psn
To see all filters do !filters
"""
request = ApiRequest(ctx.message.author)
if args[0] not in ("new", "old"):
rpcs3Bot.send_message(discord.Object(id=bot_spam_id), invalid_command_text)
"""
Gets the x (default 10) top oldest/newest updated games
Example usage:
!top old 10
!top new 10 jap
!top old 10 all
!top new 10 jap playable
!top new 10 jap playable bluray
!top new 10 jap loadable psn
To see all filters do !filters
"""
request = ApiRequest(ctx.message.author)
if args[0] not in ("new", "old"):
rpcs3Bot.send_message(discord.Object(id=bot_spam_id), invalid_command_text)
if len(args) >= 1:
if args[0] == "old":
request.set_sort("date", "asc")
request.set_custom_header(oldest_header)
else:
request.set_sort("date", "desc")
request.set_custom_header(newest_header)
if len(args) >= 2:
request.set_amount(limit_int(int(args[1]), latest_limit))
if len(args) >= 3:
request.set_region(args[2])
if len(args) >= 4:
request.set_status(args[3])
if len(args) >= 5:
request.set_release_type(args[4])
if len(args) >= 1:
if args[0] == "old":
request.set_sort("date", "asc")
request.set_custom_header(oldest_header)
else:
request.set_sort("date", "desc")
request.set_custom_header(newest_header)
if len(args) >= 2:
request.set_amount(limit_int(int(args[1]), latest_limit))
if len(args) >= 3:
request.set_region(args[2])
if len(args) >= 4:
request.set_status(args[3])
if len(args) >= 5:
request.set_release_type(args[4])
string = request.request().to_string()
await dispatch_message(string)
string = request.request().to_string()
await dispatch_message(string)
@rpcs3Bot.command(pass_context=True)
async def filters(ctx, *args):
message = "**Sorting directions (not used in top command)**\n"
message += "Ascending\n```" + str(directions["a"]) + "```\n"
message += "Descending\n```" + str(directions["d"]) + "```\n"
message += "**Regions**\n"
message += "Japan\n```" + str(regions["j"]) + "```\n"
message += "US\n```" + str(regions["u"]) + "```\n"
message += "EU\n```" + str(regions["e"]) + "```\n"
message += "Asia\n```" + str(regions["a"]) + "```\n"
message += "Korea\n```" + str(regions["h"]) + "```\n"
message += "Hong-Kong\n```" + str(regions["k"]) + "```\n"
message += "**Statuses**\n"
message += "All\n```" + str(statuses["all"]) + "```\n"
message += "Playable\n```" + "playable" + "```\n"
message += "Ingame\n```" + "ingame" + "```\n"
message += "Intro\n```" + "intro" + "```\n"
message += "Loadable\n```" + "loadable" + "```\n"
message += "Nothing\n```" + "nothing" + "```\n"
message += "**Sort Types (not used in top command)**\n"
message += "ID\n```" + "id" + "```\n"
message += "Title\n```" + "title" + "```\n"
message += "Status\n```" + "status" + "```\n"
message += "Date\n```" + "date" + "```\n"
message += "**Release Types**\n"
message += "Blu-Ray\n```" + str(release_types["b"]) + "```\n"
message += "PSN\n```" + str(release_types["n"]) + "```\n"
await rpcs3Bot.send_message(ctx.message.author, message)
message = "**Sorting directions (not used in top command)**\n"
message += "Ascending\n```" + str(directions["a"]) + "```\n"
message += "Descending\n```" + str(directions["d"]) + "```\n"
message += "**Regions**\n"
message += "Japan\n```" + str(regions["j"]) + "```\n"
message += "US\n```" + str(regions["u"]) + "```\n"
message += "EU\n```" + str(regions["e"]) + "```\n"
message += "Asia\n```" + str(regions["a"]) + "```\n"
message += "Korea\n```" + str(regions["h"]) + "```\n"
message += "Hong-Kong\n```" + str(regions["k"]) + "```\n"
message += "**Statuses**\n"
message += "All\n```" + str(statuses["all"]) + "```\n"
message += "Playable\n```" + "playable" + "```\n"
message += "Ingame\n```" + "ingame" + "```\n"
message += "Intro\n```" + "intro" + "```\n"
message += "Loadable\n```" + "loadable" + "```\n"
message += "Nothing\n```" + "nothing" + "```\n"
message += "**Sort Types (not used in top command)**\n"
message += "ID\n```" + "id" + "```\n"
message += "Title\n```" + "title" + "```\n"
message += "Status\n```" + "status" + "```\n"
message += "Date\n```" + "date" + "```\n"
message += "**Release Types**\n"
message += "Blu-Ray\n```" + str(release_types["b"]) + "```\n"
message += "PSN\n```" + str(release_types["n"]) + "```\n"
await rpcs3Bot.send_message(ctx.message.author, message)
async def dispatch_message(message: str):
"""
Dispatches messages one by one divided by the separator defined in api.config
:param message: message to dispatch
"""
for part in message.split(newline_separator):
await rpcs3Bot.send_message(discord.Object(id=channel_id), part)
"""
Dispatches messages one by one divided by the separator defined in api.config
:param message: message to dispatch
"""
for part in message.split(newline_separator):
await rpcs3Bot.send_message(discord.Object(id=channel_id), part)
@rpcs3Bot.command(pass_context=True)
async def latest(ctx, *args):
"""Get the latest RPCS3 build link"""
latest_build = json.loads(requests.get("https://update.rpcs3.net/?c=somecommit").content)['latest_build']
return await rpcs3Bot.send_message(
ctx.message.author,
"PR: {pr}\nWindows:\n\tTime: {win_time}\n\t{windows_url}\nLinux:\n\tTime: {linux_time}\n\t{linux_url}".format(
pr=latest_build['pr'],
win_time=latest_build['windows']['datetime'],
windows_url=latest_build['windows']['download'],
linux_time=latest_build['windows']['datetime'],
linux_url=latest_build['linux']['download']
)
)
"""Get the latest RPCS3 build link"""
latest_build = json.loads(requests.get("https://update.rpcs3.net/?c=somecommit").content)['latest_build']
return await rpcs3Bot.send_message(
ctx.message.author,
"PR: {pr}\nWindows:\n\tTime: {win_time}\n\t{windows_url}\nLinux:\n\tTime: {linux_time}\n\t{linux_url}".format(
pr=latest_build['pr'],
win_time=latest_build['windows']['datetime'],
windows_url=latest_build['windows']['download'],
linux_time=latest_build['windows']['datetime'],
linux_url=latest_build['linux']['download']
)
)
async def get_code(code: str) -> object:
"""
Gets the game data for a certain game code or returns None
:param code: code to get data for
:return: data or None
"""
result = ApiRequest().set_search(code).set_amount(1).request()
if len(result.results) == 1 and result.results[0].game_id == code:
return "```" + result.results[0].to_string() + "```"
return None
"""
Gets the game data for a certain game code or returns None
:param code: code to get data for
:return: data or None
"""
result = ApiRequest().set_search(code).set_amount(10).request()
if len(result.results) == 1:
for result in result.results:
if result.game_id == code:
return "```" + result.results[0].to_string() + "```"
return None
async def greet():
"""
Greets on boot!
"""
await rpcs3Bot.wait_until_ready()
await rpcs3Bot.send_message(discord.Object(id=bot_spam_id), boot_up_message)
"""
Greets on boot!
"""
await rpcs3Bot.wait_until_ready()
await rpcs3Bot.send_message(discord.Object(id=bot_spam_id), boot_up_message)
# User requests
# noinspection PyMissingTypeHints,PyMissingOrEmptyDocstring
@rpcs3Bot.command(pass_context=True)
async def roll(ctx, *args):
"""Generates a random number between 0 and n (default 10)"""
n = 10
if len(args) >= 1:
try:
n = int(args[0])
except ValueError:
pass
await rpcs3Bot.send_message(discord.Object(id=bot_spam_id), "You rolled a {}!".format(randint(0, n)))
"""Generates a random number between 0 and n (default 10)"""
n = 10
if len(args) >= 1:
try:
n = int(args[0])
except ValueError:
pass
await rpcs3Bot.send_message(discord.Object(id=bot_spam_id), "You rolled a {}!".format(randint(0, n)))
# noinspection PyMissingTypeHints,PyMissingOrEmptyDocstring
@rpcs3Bot.command(pass_context=True, name="8ball")
async def eight_ball(ctx, *args):
"""Generates a random answer to your question"""
await rpcs3Bot.send_message(discord.Object(id=bot_spam_id), choice([
"Nah mate", "Ya fo sho", "Fo shizzle mah nizzle", "Yuuuup", "Nope", "Njet", "Da", "Maybe", "I don't know",
"I don't care", "Affirmative", "Sure", "Yeah, why not", "Most likely", "Sim", "Oui", "Heck yeah!", "Roger that",
"Aye!", "Yes without a doubt m8!", "Who cares", "Maybe yes, maybe not", "Maybe not, maybe yes", "Ugh",
"Probably", "Ask again later", "Error 404: answer not found", "Don't ask me that again",
"You should think twice before asking", "You what now?", "Bloody hell, answering that ain't so easy",
"Of course not", "Seriously no", "Noooooooooo", "Most likely not", "Não", "Non", "Hell no", "Absolutely not"
]))
"""Generates a random answer to your question"""
await rpcs3Bot.send_message(discord.Object(id=bot_spam_id), choice([
"Nah mate", "Ya fo sho", "Fo shizzle mah nizzle", "Yuuuup", "Nope", "Njet", "Da", "Maybe", "I don't know",
"I don't care", "Affirmative", "Sure", "Yeah, why not", "Most likely", "Sim", "Oui", "Heck yeah!", "Roger that",
"Aye!", "Yes without a doubt m8!", "Who cares", "Maybe yes, maybe not", "Maybe not, maybe yes", "Ugh",
"Probably", "Ask again later", "Error 404: answer not found", "Don't ask me that again",
"You should think twice before asking", "You what now?", "Bloody hell, answering that ain't so easy",
"Of course not", "Seriously no", "Noooooooooo", "Most likely not", "Não", "Non", "Hell no", "Absolutely not"
]))
print(sys.argv[1])

128
math_parse.py Normal file
View File

@@ -0,0 +1,128 @@
from pyparsing import (Literal, CaselessLiteral, Word, Combine, Group, Optional,
ZeroOrMore, Forward, nums, alphas, oneOf)
import math
import operator
__author__ = 'Paul McGuire & Roberto Anic Banic'
__version__ = '$Revision: 0.1 $'
__date__ = '$Date: 2018-02-04 $'
__source__ = '''http://pyparsing.wikispaces.com/file/view/fourFn.py
http://pyparsing.wikispaces.com/message/view/home/15549426
'''
__note__ = '''
All I've done is rewrap Paul McGuire's fourFn.py as a class, so I can use it
more easily in other places.
Added cmp
'''
class NumericStringParser(object):
'''
Most of this code comes from the fourFn.py pyparsing example
'''
def pushFirst(self, strg, loc, toks):
self.exprStack.append(toks[0])
def pushUMinus(self, strg, loc, toks):
if toks and toks[0] == '-':
self.exprStack.append('unary -')
def __init__(self):
"""
expop :: '^'
multop :: '*' | '/'
addop :: '+' | '-'
integer :: ['+' | '-'] '0'..'9'+
atom :: PI | E | real | fn '(' expr ')' | '(' expr ')'
factor :: atom [ expop factor ]*
term :: factor [ multop factor ]*
expr :: term [ addop term ]*
"""
point = Literal(".")
e = CaselessLiteral("E")
fnumber = Combine(Word("+-" + nums, nums) +
Optional(point + Optional(Word(nums))) +
Optional(e + Word("+-" + nums, nums)))
ident = Word(alphas, alphas + nums + "_$")
plus = Literal("+")
minus = Literal("-")
mult = Literal("*")
div = Literal("/")
lpar = Literal("(").suppress()
rpar = Literal(")").suppress()
addop = plus | minus
multop = mult | div
expop = Literal("^")
pi = CaselessLiteral("PI")
expr = Forward()
atom = ((Optional(oneOf("- +")) +
(ident + lpar + expr + rpar | pi | e | fnumber).setParseAction(self.pushFirst))
| Optional(oneOf("- +")) + Group(lpar + expr + rpar)
).setParseAction(self.pushUMinus)
# by defining exponentiation as "atom [ ^ factor ]..." instead of
# "atom [ ^ atom ]...", we get right-to-left exponents, instead of left-to-right
# that is, 2^3^2 = 2^(3^2), not (2^3)^2.
factor = Forward()
factor << atom + \
ZeroOrMore((expop + factor).setParseAction(self.pushFirst))
term = factor + \
ZeroOrMore((multop + factor).setParseAction(self.pushFirst))
expr << term + \
ZeroOrMore((addop + term).setParseAction(self.pushFirst))
# addop_term = ( addop + term ).setParseAction( self.pushFirst )
# general_term = term + ZeroOrMore( addop_term ) | OneOrMore( addop_term)
# expr << general_term
self.bnf = expr
# map operator symbols to corresponding arithmetic operations
epsilon = 1e-12
self.opn = {"+": operator.add,
"-": operator.sub,
"*": operator.mul,
"/": operator.truediv,
"^": operator.pow}
self.fn = {"sin": math.sin,
"cos": math.cos,
"tan": math.tan,
"exp": math.exp,
"abs": abs,
"trunc": lambda a: int(a),
"round": round,
"sgn": lambda a: abs(a) > epsilon and self.cmp(a, 0) or 0}
def evaluateStack(self, s):
op = s.pop()
if op == 'unary -':
return -self.evaluateStack(s)
if op in "+-*/^":
op2 = self.evaluateStack(s)
op1 = self.evaluateStack(s)
return self.opn[op](op1, op2)
elif op == "PI":
return math.pi # 3.1415926535
elif op == "E":
return math.e # 2.718281828
elif op in self.fn:
return self.fn[op](self.evaluateStack(s))
elif op[0].isalpha():
return 0
else:
return float(op)
def eval(self, num_string, parseAll=True):
self.exprStack = []
results = self.bnf.parseString(num_string, parseAll)
val = self.evaluateStack(self.exprStack[:])
return val
def cmp(self, x, y):
"""
Replacement for built-in function cmp that was removed in Python 3
Compare the two objects x and y and return an integer according to
the outcome. The return value is negative if x < y, zero if x == y
and strictly positive if x > y.
"""
return (x > y) - (x < y)