GithubHelp home page GithubHelp logo

dxsmiley / mathbot Goto Github PK

View Code? Open in Web Editor NEW
278.0 9.0 53.0 3.87 MB

Discord bot for mathematics

Home Page: https://dxsmiley.github.io/mathbot/

License: GNU General Public License v3.0

HTML 1.40% CSS 1.28% Python 95.04% Shell 1.01% TeX 1.12% Procfile 0.15%
discord-bot bot discord-py discord

mathbot's Introduction

MathBot

MathBot is a discord bot that contains a number of features to help with mathematics.

It's primary features are:

  • LaTeX rendering
  • Querying Wolfram|Alpha
  • A Turing complete calculator

The bot is currently developed on python 3.8.10, but should work on later versions of Python.

Links

Setup for use

git clone https://github.com/DXsmiley/mathbot.git
cd mathbot
cp mathbot/parameters_default.json ./parameters.json
python3.8 -m venv .venv # or later version
source .venv/bin/activate
pip install -r requirements.txt

Then open parameters.json and change tokens to the token of the bot used for development. Optionally change the other parameters.

It is strongly recommend that you setup an instance of Redis if you want to use the bot on even a moderate scale. The disk-based keystore is easy to setup but runs very slowly, and as such is only useful of a development tool.

Run the bot with python -m mathbot parameters.json.

Setup for development

Follow above instructions, but additionally run pip install -r dev_requirements.txt

Contributing guide

Relevent discussion takes place on the MathBot Discord server.

Setting up Wolfram|Alpha

  1. Grab yourself an API key
  2. Open parameters.json and change wolfram > key.

This should really only be used for development and personal use.

Test Suite

Invoke pytest to run the test suite.

Some of the tests require that a bot is running and connected to Discord. To enable them, use the --run-automata command line argument. In addition a file with the necessary tokens filled out needs to be provided to the --parameter-file argument. To get all tests running, the token, automata and wolfram parameters need to be filled out.

For the sake of example, I run my tests with the command ./test --run-automata --parameter-file=dev.json. You should replace dev.json with a path to your own parameter file.

There are some additional tests that require a human to verify the bot's output. These can be enabled with --run-automata-human.

Guide to parameters.json

  • release : Release mode for the bot, one of "development", "beta" or "production"
  • token : Token to use for running the bot
  • wolfram
    • key : API key for making Wolfram|Alpha queries
  • keystore
    • disk
      • filename : The file to write read and write data to when in disk mode
    • redis
      • url : url used to access the redis server
      • number : the number of the database, should be a non-negative integer
    • mode : Either "disk" or "redis", depending on which store you want to use. Disk mode is not recommended for deployment.
  • patrons : list of patrons
    • Each key should be a Discord user ID.
    • Each value should be a string starting with one one of "linear", "quadratic", "exponential" or "special". The string may contains additional information after this for human use, such as usernames or other notes.
  • analytics : Keys used to post information to various bot listings.
  • automata
    • token : token to use for the automata bot
    • target : the username of the bot that the automata should target
    • channel: the ID of the channel that the tests should be run in
  • advertising
    • enable : should be true or false. When true, the bot will occasionally mention the Patreon page when running queries.
    • interval : the number of queries between mentions of the Patreon page. This is measured on a per-channel basis.
    • starting-amount : Can be increased to lower the number of commands until the Patreon page is first mention.
  • error-reporting
    • channel: ID of channel to send error reports to.
    • webhook: Webhook to send error reports to.
  • shards
    • total: The total number of shards that the bot is running on.
    • mine: A list of integers (starting at 0) specifying which shards should be run in this process.

Additional Installation Issues (Ubuntu only)

If you don't have python 3.8

sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.8

If you have installation troubles with cffi or psutil

sudo apt-get install python3.8-dev

mathbot's People

Contributors

bmintz avatar denvercoder1 avatar dependabot[bot] avatar dxsmiley avatar ioistired avatar itscryne avatar kaoffie avatar lavieestdure avatar lilizoey avatar literalgenie avatar modelmat avatar newey avatar sonataop13 avatar thebicpen avatar thenoobwar avatar xiretza avatar ytrog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mathbot's Issues

=roll with a 0 before the d causes an error.

If for example you use the command =roll 0d2 you get the message that an internal error occurred.

Steps to reproduce:

  1. Put in a command like =roll 0d2. Make sure there is a 0 for the d

image

Inline math only renders after editing the text

When I type something like

Beweis: $$ a \in A$$ blubba blubba blubba und darum $$ a = 2^{2^M} $$ weshalb $$ a \neq a $$

It does not render anything. I need to go and edit my message and change at least a character. When I confirm the edit, the MathBot starts typing and the spits out a lovely texed image, as expected.

Why do I need to edit the text to make it work?

Comparison operators not well defined in lists.

Equality operator currently checks whether two lists are the same object. It should check if the contents are the same.

Less than / greater than should compare the contents of the lists as well.

Message Content Access Deprecation for Verified Bots

Discord will be deprecating message content access for verified bots (this includes MathBot) in April 2022.

I will be applying for the message content privilege, however this isn't guaranteed.

This means that mathbot should move to slash commands.

Most commands should be fairly straightforward to convert once we've figured out a good way to do it, however there's a number of commands which could prove much more difficult.

LaTeX commends

  • Basic responses (=tex command)
  • Update output when message is edited
  • Delete output with ๐Ÿ—‘๏ธ reaction
  • "MathBot is typing" notification, since the command can run for a while.
  • Variants including texw and texp.

Note that without the message content privilege, inline LaTeX will be entirely broken. If Discord denies me there'll basically be nothing I can do about it, since I don't see a way to convert that to a slash command in a meaningful manner. If this happens, I'll update the bot to give a deprecation warning alongside any output from inline tex commands.

Wolfram Alpha

  • Basic command functionality (=wolf command)
  • Re-running commands with assumptions
  • "MathBot is typing" notification, since the command can run for a while.
  • Pup command

Calc Command

  • Should be mostly fine, but we might loose the == shortcut and have to pick something else.

Settings

  • Internals of how the settings commands work will probably have to change a lot.

redis password secured results in internal error

Tested on a clean build and new redis client.

Setting up a local host redis database secured by a password results in a NOAUTH Authentication required. error. Any incoming messages to the guild that is accessible by the bot will result in an internal error.
discord_2018-12-07_03-21-40

Bot can only access redis if it is unsecured.

Here's the error log:

ERROR:asyncio:Task exception was never retrieved
future: <Task finished coro=<Client._run_event() done, defined at /usr/local/lib/python3.6/dist-packages/discord/client.py:223> exception=AttributeError("'NoneType' object has no attribute 'lpush'",)>
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/discord/client.py", line 225, in _run_event
    await coro(*args, **kwargs)
  File "/home/Discord/MathBot/bot.py", line 75, in on_message
    context = await self.get_context(message)
  File "/usr/local/lib/python3.6/dist-packages/discord/ext/commands/bot.py", line 849, in get_context
    prefix = await self.get_prefix(message)
  File "/usr/local/lib/python3.6/dist-packages/discord/ext/commands/bot.py", line 794, in get_prefix
    ret = await discord.utils.maybe_coroutine(prefix, self, message)
  File "/usr/local/lib/python3.6/dist-packages/discord/utils.py", line 274, in maybe_coroutine
    return (await value)
  File "/home/Discord/MathBot/bot.py", line 226, in _determine_prefix
    custom = str(await bot.settings.get_server_prefix(message))
  File "/home/Discord/MathBot/core/settings.py", line 87, in get_server_prefix
    stored = await self.keystore.get(f's-prefix:{context.id}')
  File "/home/Discord/MathBot/core/keystore.py", line 208, in get
    return await self.driver.get(key)
  File "/home/Discord/MathBot/core/keystore.py", line 85, in get
    return self.decipher(await self.connection.get(key))
AttributeError: 'NoneType' object has no attribute 'get'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/discord/client.py", line 230, in _run_event
    await self.on_error(event_name, *args, **kwargs)
  File "/home/Discord/MathBot/bot.py", line 126, in on_error
    await self.handle_contextual_error(args[0].channel, error, msg)
  File "/home/Discord/MathBot/bot.py", line 163, in handle_contextual_error
    await self.report_error(destination, error, human_details)
  File "/home/Discord/MathBot/bot.py", line 178, in report_error
    await report(self, f'{self.shard_ids} {human_details}\n```\n{tb}\n```')
  File "/home/Discord/MathBot/modules/reporter.py", line 69, in report
    await bot.keystore.lpush('error-report', string)
  File "/home/Discord/MathBot/core/keystore.py", line 236, in lpush
    await self.driver.lpush(key, value)
  File "/home/Discord/MathBot/core/keystore.py", line 101, in lpush
    return await self.connection.lpush(key, value)
AttributeError: 'NoneType' object has no attribute 'lpush'

I believe the fix can be found within:
Line 64 in mathbot/core/keystore.py

               self.connection = await aioredis.create_reconnecting_redis(
                    (host, int(port)),
                    password = password,
                    db = self.db_number
                )

Returns with this error
AttributeError: module 'aioredis' has no attribute 'create_reconnecting_redis'

Adding physics package

I'd understand you wouldn't want to add every random package someone suggests, so I'm going to suggest one anyway: the physics package. I use discord a lot to communicate with my fellow physics students and this package is used very often.
Here are the docs.
I hope you'll consider adding it to your template, it would make quickly writing derivatives and such a lot easier. It would make the bot compatible with our reports, so we can just copy paste pieces back and forth.

Thanks!

Add contants for handling infinities

Operations such as tan(pi / 2) produce a value, zoo, which is something from Sympy.

  • Investigate what this value is.
  • Add a constant value to the calculator to access it easily.
  • Give it a better representation.
  • Add it to the user documentation.

CalcuLaTeX support

I've a project called CalcuLaTeX which I think would be a useful function for this bot.

It's available as a python library interface to the Rust library, so it should be pretty simple to integrate. Currently it's compiled for Linux so you can run pip install calculatex-py on Linux and it should work, but it would be pretty trivial to compile it for Windows as well.

If you give the OK I'll write a PR, unless you'd like to do it yourself.

[BUG] Backticks in =tex are not converted to left quotes

In regular LaTeX using backticks (`) converts them to left quotes (โ€˜), however, this does not seem to work in the =tex command. Things like =tex \text{``hello''} seem to be equivalent to just typing =tex \text{hello''}. In order to insert real left quotes with =tex one has to use the actual unicode character for left quotes (โ€˜) in their message.

From some digging around I believe that it might be related to this:

latex = latex.replace('`', ' ').strip(' \n')

OEIS `JSONDecodeError`

I got an internal error when I tried =oeis \. So I took a look at oeis.py and found:

async with aiohttp.ClientSession() as session:
    params = {
        'q': query,
        'start': 0,
        'fmt': 'json'
    }
    async with session.get('https://oeis.org/search', params=params, timeout=10) as req:
        j = await req.json()

It seems that when query="\\", OEIS returns <b>Could not parse search query: empty query</b>, resulting in req.json() causing a JSONDecodeError.

modules/tex/template.tex: allow the unicode prime symbol instead of \prime

I don't really know how to do this, but is it possible to allow "โ€ฒ" (U+2032 PRIME), "โ€‰โ€ณ" (U+2033 DOUBLE PRIME), "โ€ด" (U+2034 TRIPLE PRIME), and "โ—" (U+2057 QUADRUPLE PRIME) to be used?
For example, (f^{-1})^โ€ฒ instead of (f^{-1})^{\prime}

The first one would be defined as \prime but I don't know what the rest should be defined as.

`v7` and `v6` Discord API gateway decommission is imminent.

Hello,

I wanted to make an issue about this since the latest stable version of discord.py v1.7.3 and any previous version of discord.py are about to no longer work due to the imminent decommissioning of v7 and v6 Discord API gateway. The current plan is to decommission them on April 30th, see here for reference. It seems like the only option is to rewrite the bot as @Rapptz (the creator of discord.py) is not willing to push out a legacy version to support bots using the old version 1.x framework to extend their life, see here for reference (you must be in the discord.py Discord server to see this message). Will this bot die on April 30th or are there plans to update the bot's code in that timeframe?

Thank you,
@Ahsoka

Add graphviz DOT support

well, it'd be nice if it supported graphs too, as in networks where you could specify the graph and it'd draw it for you. You could use the graphviz package for that, but do you support latex packages?

I tried

\usepackage[pdf]{graphviz}

\begin{document}
\digraph[scale=0.5]{abc}{rankdir=LR; a->b->c
a [label=<foo<SUP>bar</SUP>>];}
\end{document}

But the bot kept throwing errors, how'd you make it accept graphviz if it is supported?

[feature request] allow custom preamble

TeXit has this feature. That would allow users to add whatever package/cmd they want, say PGF plots for automize axis setup, or a user-defined string for a specific color. A user sends a preamble modification request to the Discord bot, who would approve/reject that in a short period of time.

Feature request: Option to mark Mathbot response as spoiler

It would be nice to have some way to tell mathbot to mark its response as a spoiler.

I am using Discord in my classes and sometimes post additional practice problems to the chat. I would like to add solutions as well, but I want them to be hidden behind the spoiler click.

Perhaps a parallel set of commands that ends with "s" could invoke this behavior, e.g., =texs x^2 would mark the typeset image as a spoiler.

Calling display() causes "Improper number of arguments for function Function join"

==display(1)

Runtime error in _system_library
On line 189 at position 20

display(x.) = \join(expand(map(i -> ; :str(i), x)))
                   ^
Improper number of arguments for function Function join @โ€Œ140628762953936-0
==display(1 2)

"1 2"
==display(1 2 3)

Runtime error in _system_library
On line 189 at position 20

display(x.) = \join(expand(map(i -> ; :str(i), x)))
                   ^
Improper number of arguments for function Function join @โ€Œ140628762953936-0

I believe this is because join is being called directly, instead of being folded. It looks like join in the past used to be variadic, before reduce was removed. Perhaps join could be changed to

_join(a b) = if (!a b 'a:_join(\a b)) # current definition of join()
join(xs.) = foldr(_join [] xs)

Then display would be able to call join variadically, as it is now

Possible to load packages into LaTeX mode of mathbot?

I just tried to use \mathds{R} to get the symbol for real numbers. As expected, it didn't work. I was thinking... Maybe there is a way to realize it? Maybe to give the writer the option to load some packages, or preload some of the most common ones?

complex calculations in MathBot?

How can I do complex numbers in MathBot, like calculating the amplitude, phase, real part imaginary part of a complex number?

Adding Asciimath

So it would be super awesome if we let the user input asciimath which is just a lot easier than latex (especially for younger students), I don't how how hard that would be based on the way you've designed it. But I was thinking a simple asciimath to latex converter would be cool, then users could just do:

This is some $$\LaTeX$$ and this is some $$+text(AsciiMath)+$

The asciimath would just get converted to latex and sent to your current renderer. Thoughts?

AttributeError when trying to run the calculator against a file

โžค python -m calculator tmp/script.c5
Traceback (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/user/code/vcs/git/com/github/@/DXsmiley/mathbot/mathbot/calculator/__main__.py", line 79, in <module>
    main()
  File "/home/user/code/vcs/git/com/github/@/DXsmiley/mathbot/mathbot/calculator/__main__.py", line 27, in main
    btc = prepare_runtime(bytecode.CodeBuilder(), ast, exportable = args.compile)
AttributeError: module 'calculator.bytecode' has no attribute 'CodeBuilder'

I'm on commit a6b8fea. I tried with the --compile / --trace flags, and got the same error.

Is sympy broken or am I doing something stupid?

On running python3.6 entrypoint.py, I get this message:

Main process starting up
Could not find gateway queue to connect to
Running shards [0] (total 1)
/usr/local/lib/python3.6/dist-packages/discord/client.py:250: DeprecationWarning: fetch_offline_members is deprecated, use chunk_guilds_at_startup instead
  self._connection = self._get_state(**options)
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/discord/ext/commands/bot.py", line 607, in _load_from_module_spec
    spec.loader.exec_module(lib)
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/disrupt/discordbots/mathbot/mathbot/modules/calcmod.py", line 10, in <module>
    import calculator
  File "/home/disrupt/discordbots/mathbot/mathbot/calculator/__init__.py", line 11, in <module>
    import calculator.interpereter
  File "/home/disrupt/discordbots/mathbot/mathbot/calculator/interpereter.py", line 14, in <module>
    import calculator.runtime as runtime
  File "/home/disrupt/discordbots/mathbot/mathbot/calculator/runtime.py", line 13, in <module>
    from calculator.bytecode import *
  File "/home/disrupt/discordbots/mathbot/mathbot/calculator/bytecode.py", line 3, in <module>
    import calculator.errors
  File "/home/disrupt/discordbots/mathbot/mathbot/calculator/errors.py", line 2, in <module>
    import calculator.formatter
  File "/home/disrupt/discordbots/mathbot/mathbot/calculator/formatter.py", line 14, in <module>
    ALL_SYMPY_CLASSES = tuple(sympy.core.all_classes) # pylint: disable=no-member
AttributeError: module 'sympy.core' has no attribute 'all_classes'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "entrypoint.py", line 49, in <module>
    bot.run(retrieve_parameters())
  File "/home/disrupt/discordbots/mathbot/mathbot/bot.py", line 271, in run
    MathBot(parameters).run()
  File "/home/disrupt/discordbots/mathbot/mathbot/bot.py", line 72, in __init__
    self.load_extension(i)
  File "/usr/local/lib/python3.6/dist-packages/discord/ext/commands/bot.py", line 664, in load_extension
    self._load_from_module_spec(spec, name)
  File "/usr/local/lib/python3.6/dist-packages/discord/ext/commands/bot.py", line 610, in _load_from_module_spec
    raise errors.ExtensionFailed(key, e) from e
discord.ext.commands.errors.ExtensionFailed: Extension 'modules.calcmod' raised an error: AttributeError: module 'sympy.core' has no attribute 'all_classes'

I think I'm stupid idk what's going on, I can't figure out any way to fix this

Comma for number seperation, comma for thousand power seperation

Reading a list like

[6, 12, 18, 30, 48, 78, 126, 204, 330, 534, 864, 1โ€š398, 2โ€š262, 3โ€š660, 5โ€š922, 9โ€š582, 15โ€š504, 25โ€š086, 40โ€š590, 65โ€š676, 106โ€š266, 171โ€š942, 278โ€š208, 450โ€š150, 728โ€š358, 1โ€š178โ€š508, 1โ€š906โ€š866, 3โ€š085โ€š374, 4โ€š992โ€š240, 8โ€š077โ€š614, 13โ€š069โ€š854, 21โ€š147โ€š468, 34โ€š217โ€š322, 55โ€š364โ€š790, 89โ€š582โ€š112, 144โ€š946โ€š902, 234โ€š529โ€š014, 379โ€š475โ€š916, 614โ€š004โ€š930, 993โ€š480โ€š846, 1โ€š607โ€š485โ€š776, 2โ€š600โ€š966โ€š622, 4โ€š208โ€š452โ€š398, 6โ€š809โ€š419โ€š020, 11โ€š017โ€š871โ€š418, 17โ€š827โ€š290โ€š438, 28โ€š845โ€š161โ€š856, 46โ€š672โ€š452โ€š294, 75โ€š517โ€š614โ€š150, 122โ€š190โ€š066โ€š444, 197โ€š707โ€š680โ€š594, 319โ€š897โ€š747โ€š038, 517โ€š605โ€š427โ€š632, 837โ€š503โ€š174โ€š670, 1โ€š355โ€š108โ€š602โ€š302, 2โ€š192โ€š611โ€š776โ€š972, 3โ€š547โ€š720โ€š379โ€š274, 5โ€š740โ€š332โ€š156โ€š246, 9โ€š288โ€š052โ€š535โ€š520, 15โ€š028โ€š384โ€š691โ€š766, 24โ€š316โ€š437โ€š227โ€š286, 39โ€š344โ€š821โ€š919โ€š052, 63โ€š661โ€š259โ€š146โ€š338, 103โ€š006โ€š081โ€š065โ€š390, 166โ€š667โ€š340โ€š211โ€š728, 269โ€š673โ€š421โ€š277โ€š118, 436โ€š340โ€š761โ€š488โ€š846, 706โ€š014โ€š182โ€š765โ€š964, 1โ€š142โ€š354โ€š944โ€š254โ€š810, 1โ€š848โ€š369โ€š127โ€š020โ€š774, 2โ€š990โ€š724โ€š071โ€š275โ€š584, 4โ€š839โ€š093โ€š198โ€š296โ€š358, 7โ€š829โ€š817โ€š269โ€š571โ€š942, 12โ€š668โ€š910โ€š467โ€š868โ€š300, 20โ€š498โ€š727โ€š737โ€š440โ€š242, 33โ€š167โ€š638โ€š205โ€š308โ€š542, 53โ€š666โ€š365โ€š942โ€š748โ€š784, 86โ€š834โ€š004โ€š148โ€š057โ€š326, 140โ€š500โ€š370โ€š090โ€š806โ€š110, 227โ€š334โ€š374โ€š238โ€š863โ€š436, 367โ€š834โ€š744โ€š329โ€š669โ€š546, 595โ€š169โ€š118โ€š568โ€š532โ€š982, 963โ€š003โ€š862โ€š898โ€š202โ€š528, 1โ€š558โ€š172โ€š981โ€š466โ€š735โ€š510, 2โ€š521โ€š176โ€š844โ€š364โ€š938โ€š038, 4โ€š079โ€š349โ€š825โ€š831โ€š673โ€š548, 6โ€š600โ€š526โ€š670โ€š196โ€š611โ€š586, 10โ€š679โ€š876โ€š496โ€š028โ€š285โ€š134, 17โ€š280โ€š403โ€š166โ€š224โ€š896โ€š720, 27โ€š960โ€š279โ€š662โ€š253โ€š181โ€š854, 45โ€š240โ€š682โ€š828โ€š478โ€š078โ€š574, 73โ€š200โ€š962โ€š490โ€š731โ€š260โ€š428, 118โ€š441โ€š645โ€š319โ€š209โ€š339โ€š002, 191โ€š642โ€š607โ€š809โ€š940โ€š599โ€š430, 310โ€š084โ€š253โ€š129โ€š149โ€š938โ€š432, 501โ€š726โ€š860โ€š939โ€š090โ€š537โ€š862, 811โ€š811โ€š114โ€š068โ€š240โ€š476โ€š294, 1โ€š313โ€š537โ€š975โ€š007โ€š331โ€š014โ€š156, 2โ€š125โ€š349โ€š089โ€š075โ€š571โ€š490โ€š450, 3โ€š438โ€š887โ€š064โ€š082โ€š902โ€š504โ€š606, 5โ€š564โ€š236โ€š153โ€š158โ€š473โ€š995โ€š056, 9โ€š003โ€š123โ€š217โ€š241โ€š376โ€š499โ€š662]

Is very hard, maybe try space for powers of thousand and comma for number seperation?

Pipenv command is non-existent

I am attempting to use the bot on Windows 10. I have python installed to PATH and I cloned the repository, and I attempted to troubleshoot it by installing the "pipenv" library.

Prevent multiple `=calc` commands running at once.

It is currently possible to have multiple =calc commands evaluating at the same time in the same channel. Due to the way the interpreter works, this results in undefined behavior. The later commands should wait for the earlier ones to complete before being executed.

Minor grammatical issue

When only 1 sequence is found in OEIS, the bot says "There were 1 relevant sequences. Here is one:" when instead it would be more correct to say "There was 1 relevant sequence:"

image

Feature: Step by step solutions

Wolfram Alpha provides step by step solutions for some problems through their API.

This would be an extremely useful feature for this bot and it shouldn't be difficult to implement assuming you already use the WA API.

More details: https://products.wolframalpha.com/show-steps-api/documentation/

Example query: Note: it is required to pass an APIKEY (which I have removed for privacy)

https://api.wolframalpha.com/v2/query?appid=APIKEY&input=integral%20x^3%20ln^2%20x%20dx&podstate=Step-by-step%20solution&format=image

Query result
<?xml version='1.0' encoding='UTF-8'?>
<queryresult success='true'
    error='false'
    xml:space='preserve'
    numpods='5'
    datatypes=''
    timedout=''
    timedoutpods=''
    timing='4.075'
    parsetiming='0.507'
    parsetimedout='false'
    recalculate=''
    id='MSP6227185ba9226487e03500005534f25c7f5690h1'
    host='https://www5a.wolframalpha.com'
    server='42'
    related='https://www5a.wolframalpha.com/api/v1/relatedQueries.jsp?id=MSPa6228185ba9226487e03500001ecg2hc0g7afb47f3773634836471742935'
    version='2.6'
    inputstring='integral x^3 ln^2 x dx'>
 <pod title='Indefinite integrals'
     scanner='Integral'
     id='IndefiniteIntegral'
     position='100'
     error='false'
     numsubpods='2'
     primary='true'>
  <subpod title=''>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6229185ba9226487e03500004f6ia342d3595215?MSPStoreType=image/gif&amp;s=42'
       alt='integral x^3 log^2(x) dx = 1/32 x^4 (8 log^2(x) - 4 log(x) + 1) + constant'
       title='integral x^3 log^2(x) dx = 1/32 x^4 (8 log^2(x) - 4 log(x) + 1) + constant'
       width='403'
       height='38'
       type='Default'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
  </subpod>
  <subpod title='Possible intermediate steps'>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6230185ba9226487e03500002b8b54i9604c3i4a?MSPStoreType=image/gif&amp;s=42'
       alt='Take the integral:
 integral x^3 log^2(x) dx
For the integrand x^3 log^2(x), integrate by parts, integral f dg = f g - integral g df, where 
 f = log^2(x), dg = x^3 dx, df = (2 log(x))/x dx, g = x^4/4:
 = 1/4 x^4 log^2(x) - 1/4 integral2 x^3 log(x) dx
Factor out constants:
 = 1/4 x^4 log^2(x) - 1/2 integral x^3 log(x) dx
For the integrand x^3 log(x), integrate by parts, integral f dg = f g - integral g df, where 
 f = log(x), dg = x^3 dx, df = 1/x dx, g = x^4/4:
 = -1/8 x^4 log(x) + 1/4 x^4 log^2(x) + 1/8 integral x^3 dx
The integral of x^3 is x^4/4:
 = x^4/32 + 1/4 x^4 log^2(x) - 1/8 x^4 log(x) + constant
Which is equal to:
Answer: | 
 | = 1/32 x^4 (8 log^2(x) - 4 log(x) + 1) + constant'
       title='Take the integral:
 integral x^3 log^2(x) dx
For the integrand x^3 log^2(x), integrate by parts, integral f dg = f g - integral g df, where 
 f = log^2(x), dg = x^3 dx, df = (2 log(x))/x dx, g = x^4/4:
 = 1/4 x^4 log^2(x) - 1/4 integral2 x^3 log(x) dx
Factor out constants:
 = 1/4 x^4 log^2(x) - 1/2 integral x^3 log(x) dx
For the integrand x^3 log(x), integrate by parts, integral f dg = f g - integral g df, where 
 f = log(x), dg = x^3 dx, df = 1/x dx, g = x^4/4:
 = -1/8 x^4 log(x) + 1/4 x^4 log^2(x) + 1/8 integral x^3 dx
The integral of x^3 is x^4/4:
 = x^4/32 + 1/4 x^4 log^2(x) - 1/8 x^4 log(x) + constant
Which is equal to:
Answer: | 
 | = 1/32 x^4 (8 log^2(x) - 4 log(x) + 1) + constant'
       width='524'
       height='806'
       type='Default'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
   <infos count='1'>
    <info text='log(x) is the natural logarithm'>
     <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6231185ba9226487e0350000681d47e441725b11?MSPStoreType=image/gif&amp;s=42'
         alt='log(x) is the natural logarithm'
         title='log(x) is the natural logarithm'
         width='198'
         height='19' />
     <link url='http://reference.wolfram.com/language/ref/Log.html'
         text='Documentation'
         title='Mathematica' />
     <link url='http://functions.wolfram.com/ElementaryFunctions/Log'
         text='Properties'
         title='Wolfram Functions Site' />
     <link url='http://mathworld.wolfram.com/NaturalLogarithm.html'
         text='Definition'
         title='MathWorld' />
    </info>
   </infos>
  </subpod>
  <expressiontypes count='2'>
   <expressiontype name='Default' />
   <expressiontype name='Default' />
  </expressiontypes>
  <states count='1'>
   <state name='Hide steps'
       input='IndefiniteIntegral__Hide steps' />
  </states>
 </pod>
 <pod title='Plots of the integral'
     scanner='Integral'
     id='Plot'
     position='200'
     error='false'
     numsubpods='2'>
  <subpod title=''>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6232185ba9226487e03500002g128g6cea8c7894?MSPStoreType=image/gif&amp;s=42'
       alt='Plots of the integral'
       title=''
       width='335'
       height='134'
       type='2DMathPlot_1'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
  </subpod>
  <subpod title=''>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6233185ba9226487e035000027cc6ig523diai4d?MSPStoreType=image/gif&amp;s=42'
       alt='Plots of the integral'
       title=''
       width='335'
       height='135'
       type='2DMathPlot_1'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
  </subpod>
  <expressiontypes count='2'>
   <expressiontype name='2DMathPlot' />
   <expressiontype name='2DMathPlot' />
  </expressiontypes>
  <states count='1'>
   <statelist count='2'
       value='Complex-valued plots'
       delimiters=''>
    <state name='Complex-valued plots'
        input='Plot__Complex-valued plots' />
    <state name='Real-valued plots'
        input='Plot__Real-valued plots' />
   </statelist>
  </states>
 </pod>
 <pod title='Alternate form of the integral'
     scanner='Integral'
     id='AlternateFormOfTheIntegral'
     position='300'
     error='false'
     numsubpods='1'>
  <subpod title=''>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6234185ba9226487e03500001050902e1ii63fea?MSPStoreType=image/gif&amp;s=42'
       alt='x^4 ((log^2(x))/4 - log(x)/8 + 1/32) + constant'
       title='x^4 ((log^2(x))/4 - log(x)/8 + 1/32) + constant'
       width='255'
       height='49'
       type='Default'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
  </subpod>
  <expressiontypes count='1'>
   <expressiontype name='Default' />
  </expressiontypes>
 </pod>
 <pod title='Expanded form of the integrals'
     scanner='Integral'
     id='ExpandedFormOfTheIntegral'
     position='400'
     error='false'
     numsubpods='2'>
  <subpod title=''>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6235185ba9226487e035000052h887g2a766d42f?MSPStoreType=image/gif&amp;s=42'
       alt='x^4/32 + 1/4 x^4 log^2(x) - 1/8 x^4 log(x) + constant'
       title='x^4/32 + 1/4 x^4 log^2(x) - 1/8 x^4 log(x) + constant'
       width='285'
       height='43'
       type='Default'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
  </subpod>
  <subpod title='Possible intermediate steps'>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6236185ba9226487e03500005d4ffa71b9ga81aa?MSPStoreType=image/gif&amp;s=42'
       alt='Expand the following:
(x^4 (1 - 4 log(x) + 8 log(x)^2))/32
x^4 (1 - 4 log(x) + 8 log(x)^2) = x^4ร—1 + x^4 (-4 log(x)) + x^4ร—8 log(x)^2:
(x^4 - 4 x^4 log(x) + 8 x^4 log(x)^2)/32
(x^4 - 4 x^4 log(x) + 8 x^4 log(x)^2)/32 = x^4/32 - (4 x^4 log(x))/32 + (8 x^4 log(x)^2)/32:
x^4/32 - (4 x^4 log(x))/32 + (8 x^4 log(x)^2)/32
The gcd of -4 and 32 is 4, so (-4 x^4 log(x))/32 = ((4 (-1)) x^4 log(x))/(4ร—8) = 4/4ร—(-x^4 log(x))/8 = (-x^4 log(x))/8:
x^4/32 + (-1 x^4 log(x))/8 + (8 x^4 log(x)^2)/32
8/32 = 8/(8ร—4) = 1/4:
Answer: | 
 | x^4/32 - (x^4 log(x))/8 + (x^4 log(x)^2)/4'
       title='Expand the following:
(x^4 (1 - 4 log(x) + 8 log(x)^2))/32
x^4 (1 - 4 log(x) + 8 log(x)^2) = x^4ร—1 + x^4 (-4 log(x)) + x^4ร—8 log(x)^2:
(x^4 - 4 x^4 log(x) + 8 x^4 log(x)^2)/32
(x^4 - 4 x^4 log(x) + 8 x^4 log(x)^2)/32 = x^4/32 - (4 x^4 log(x))/32 + (8 x^4 log(x)^2)/32:
x^4/32 - (4 x^4 log(x))/32 + (8 x^4 log(x)^2)/32
The gcd of -4 and 32 is 4, so (-4 x^4 log(x))/32 = ((4 (-1)) x^4 log(x))/(4ร—8) = 4/4ร—(-x^4 log(x))/8 = (-x^4 log(x))/8:
x^4/32 + (-1 x^4 log(x))/8 + (8 x^4 log(x)^2)/32
8/32 = 8/(8ร—4) = 1/4:
Answer: | 
 | x^4/32 - (x^4 log(x))/8 + (x^4 log(x)^2)/4'
       width='450'
       height='666'
       type='Default'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
  </subpod>
  <expressiontypes count='2'>
   <expressiontype name='Default' />
   <expressiontype name='Default' />
  </expressiontypes>
  <states count='1'>
   <state name='Hide steps'
       input='ExpandedFormOfTheIntegral__Hide steps' />
  </states>
 </pod>
 <pod title='Definite integral'
     scanner='Integral'
     id='DefiniteIntegral'
     position='500'
     error='false'
     numsubpods='1'>
  <subpod title=''>
   <img src='https://www5a.wolframalpha.com/Calculate/MSP/MSP6237185ba9226487e03500005g0baeieh53cd3c0?MSPStoreType=image/gif&amp;s=42'
       alt='integral_0^1 x^3 log^2(x) dx = 1/32 = 0.03125'
       title='integral_0^1 x^3 log^2(x) dx = 1/32 = 0.03125'
       width='224'
       height='38'
       type='Default'
       themes='1,2,3,4,5,6,7,8,9,10,11,12'
       colorinvertable='true' />
  </subpod>
  <expressiontypes count='1'>
   <expressiontype name='Default' />
  </expressiontypes>
 </pod>
</queryresult>

The second link (https://www4b.wolframalpha.com/Calculate/MSP/MSP20411ebib521338c9a5800005h54e68eb6i7i8f4?MSPStoreType=image/gif&s=38) displays this image:

Example step by step image

image

If this could be implemented, that would be awesome.

Thanks!

MathBot responds to other bots

The title says it all. The bot shouldn't be responding to other bots.

Easiest solution is to put if message.author.bot: return in on_message

Add quaternions to calc

There is already support for complex numbers. For calculations involving rotations in 3D quaternions might be a good addition to the calculator.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.