mirror of
https://github.com/RPCS3/discord-bot.git
synced 2026-01-31 01:25:22 +01:00
Math & Fix Gamecodes
This commit is contained in:
290
bot.py
290
bot.py
@@ -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
128
math_parse.py
Normal 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)
|
||||
Reference in New Issue
Block a user