← Voltar ao Marketplace Tools
Banner de Disculate
Ícone de Disculate

Disculate

Plugin do Discord · Tools
por Paul
v0.0.15

A discord friendly calculator tool.

captura de tela Disculate 1
captura de tela Disculate 2
captura de tela Disculate 3
captura de tela Disculate 4

Comandos que este plugin adiciona

/calc /calc-config /calc-help

Sobre este plugin

Disculate

An in-Discord calculator plugin for YourBot. Arithmetic, percentages, common math functions, and constants — without leaving the channel.

You: /calc expression: (3 + 4) * sqrt(16)

Disculate: (3 + 4) * sqrt(16) = 28

Built for the YourBot platform's sandboxed plugin runtime (yourbot_sdk; the platform was formerly branded "MMO Maid"). Safe-tier capabilities only (interaction:respond, storage:kv). No outbound HTTP, no disk writes, no eval/exec/compile on user input.

Slash commands

Command Who Purpose
/calc expression:<text> [ephemeral:<bool>] Anyone Evaluate a math expression. ephemeral:true hides the result from the channel.
/calc-config [precision:<int>] [angle_mode:<rad|deg>] [scientific_threshold:<int>] Server admin (MANAGE_GUILD) Set per-server defaults. Omitted options keep their current value.
/calc-help Anyone Quick reference for syntax, functions, and constants.

Supported syntax

Operators: + - * / // ** unary +/- parentheses

Percent: trailing % divides by 100 (e.g. 50%0.5, 200 * 5%10)

Constants (case-sensitive): pi e tau

Functions:

Category Names
Basic abs(x) round(x[, n]) floor(x) ceil(x) min(a, b, ...) max(a, b, ...) mod(a, b) pow(a, b) gcd(a, b) lcm(a, b) trunc(x) hypot(x, y) sign(x)
Roots / exp / log sqrt(x) cbrt(x) exp(x) log(x[, base]) log10(x) log2(x) ln(x)
Trig (honours angle_mode) sin cos tan asin acos atan atan2(y, x)
Hyperbolic sinh(x) cosh(x) tanh(x) asinh(x) acosh(x) atanh(x)

Examples

Input Output
2 + 2 = 4
1/3 = 0.333333 (precision-dependent)
200 * 5% = 10
100 + 10% = 100.1 (10% = 0.1, not "10% of 100"; see ARCHITECTURE.md §B)
sqrt(2) = 1.414214
sin(30) with angle_mode:deg = 0.5
mod(-7, 3) = 2 (sign-of-divisor)
(2+1)*7-8 = 13 with a Steps field showing the three intermediate computations
1e308 * 10 error: Result is too large to represent.
2^3 error: Use ** for power, not ^ (which would be bitwise XOR).
5 % 3 error: Use mod(a, b) for modulo. Trailing % means percent (e.g. 50% = 0.5).
sqirt(2) error: Unknown function sqirt. Did you mean sqrt?
Pi + 1 error: Unknown name Pi. Constants are case-sensitive. Did you mean pi?
((1+2) error: Unclosed parenthesis. 1 more ( than ). Add 1 ) to balance the expression.
sqrt(-1) error: sqrt of a negative value isn't a real number. Try sqrt(abs(x)) if you want the magnitude.

Errors aren't generic. Disculate identifies the specific problem in your input — close-typo suggestions for unknown names and functions, paren-balance counts, function-specific domain explanations, operator-mistake hints. Every error embed shows what's wrong on top, how to fix it next, a reason: <code> footer for tracking, and a Show help button that swaps the error for the full syntax reference in place — one message, not two.

/calc-help leads with a Commands overview and adapts to the server: a fresh install (nothing configured yet) sees a numbered Getting started quick-start; a configured server sees its live Server settings. Running /calc-config with no options shows the current settings plus a one-click Switch to degrees / radians button so an admin can fix the most common trig surprise without learning the option syntax.

Configuration

/calc-config adjusts three per-server settings, persisted in plugin KV:

Setting Range Default
precision 010 decimal places 6
angle_mode rad / deg rad
scientific_threshold 120 (switch to scientific notation when |result| ≥ 10^N) 12

A per-user cooldown of 2 seconds prevents accidental spam. Errors are always shown ephemerally to the invoker only.

Safety model

  • No eval / exec / compile on user input. The parser uses stdlib ast.parse(mode="eval") and a manual node-allowlist walker. The audit gate (tools/run_audit.py) scans for these calls and blocks any from being committed.
  • Defense-in-depth DoS guards: 120-char input cap, 32-deep AST cap, 200-node AST cap, ** operand guard that routes large operands through math.pow (so bignums can't OOM the sandbox), and a 200 ms wall-clock budget.
  • Mention injection defeated at two layers: safe_text inserts zero-width spaces between @ and everyone/here, and every response sets allowed_mentions: {"parse": []}.
  • NFKC normalisation + bidi/control-char rejection on every input before parsing.

See AUDIT-REPORT.md for the full audit trail.

Local development

# Requirements: Python 3.11+ (tested on 3.11–3.14)
# Dev deps (test runner + the SDK whose vendored validator the audit uses):
py -m pip install -r requirements-dev.txt

# Run the test suite (333 tests, ~0.2s)
py -m pytest tests/ -q

# Build the deterministic production bundle (build/disculate.zip)
py tools/build_bundle.py

# Run all 9 audit gates (manifest, imports, blocked_substrings, no_eval_ast,
#                       todo_markers, plugin_run, pytest, bundle,
#                       platform_validator)
py tools/run_audit.py

The bundle excludes everything outside an explicit allowlist (see tools/build_bundle.py:INCLUDED_FILES). Tests, tools, documentation, dotfiles, and assets/ never ship — Discord fetches the brand image directly from the GitHub raw URL.

Project layout

disculate/
├── manifest.json            ← plugin id, capabilities, slash commands
├── __main__.py              ← entry point the platform requires; just imports plugin
├── plugin.py                ← handler entry points (must end with plugin.run())
├── assets/
│   └── disculate.webp       ← brand thumbnail, referenced by Discord via GitHub raw URL
├── lib/
│   ├── parser.py            ← cleaning, percent preprocessing, ast.parse + allowlist walker
│   ├── walker.py            ← AST walk, DoS guards, wall-clock budget, step trace
│   ├── functions.py         ← FunctionSpec registry (one entry per math function)
│   ├── format.py            ← result formatting (precision, scientific, int preservation)
│   ├── config.py            ← per-server KV config + schema versioning
│   ├── embed.py             ← response builders + safe_text/clip/help generation
│   ├── diagnostics.py       ← per-reason error explainer + did-you-mean
│   ├── reasons.py           ← reason codes + user-facing hints
│   └── logctx.py            ← request_id ContextVar for log correlation
├── tests/                   ← 333 tests: smoke, unit, handler, failure-injection, adversarial,
│                              diagnostics, bundle/platform contract, drift guards, components
├── tools/
│   ├── build_bundle.py      ← deterministic zip with allowlist guard
│   ├── run_audit.py         ← 9 audit gates (incl. marketplace-substring mirror)
│   └── validate_artifact.py ← runs the platform's vendored upload validator on the zip
└── docs (CLAUDE.md, AUDIT-REPORT.md, ARCHITECTURE.md, RUNBOOK.md, SDK-ASSUMPTIONS.md, CHANGELOG.md)

Documentation

Document Audience
README.md Users + first-time contributors. You are here.
CLAUDE.md The next maintainer (or LLM). TL;DR, recipes, things-that-look-wrong-but-aren't.
ARCHITECTURE.md Why each design decision beat its alternatives.
AUDIT-REPORT.md Full audit trail across R1, R2, R3, and the math-shape Tailored round.
SDK-ASSUMPTIONS.md Every defensive try/except that exists because the SDK doc was incomplete — the post-deploy probe list.
RUNBOOK.md Operational scenarios: OOM, KV quota, schema migration, rollback.
CHANGELOG.md Per-version Added / Changed / Fixed.

Contributing

The single-paragraph recipe for "add a math function" is in CLAUDE.md → Common task recipes. The audit gates in tools/run_audit.py are the merge bar: if py tools/run_audit.py exits non-zero, the change isn't shippable.

Before opening a PR:

py -m pytest tests/ -q   # all green
py tools/run_audit.py    # all 9 gates pass

License

This repository ships without a LICENSE file. Under default GitHub / copyright terms that means all rights reserved to the author — the source is publicly readable, but redistribution, derivative works, and commercial use are not granted. A formal open-source license may be added later; until then, please open an issue if you'd like to use any of this code outside the context of forking + contributing back.

Plugins relacionados

Tem alguma pergunta?

Faça uma pergunta diretamente ao desenvolvedor de Disculate. Entre com Discord para enviar sua pergunta. Você será notificado quando responderem.

Faça login para perguntar ao desenvolvedor →

Pronto para instalar Disculate?

Entre com Discord, configure seu servidor e adicione-o em minutos.

Instalar no seu servidor →
Visualização de captura de tela