chore: import upstream snapshot with attribution
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:17:32 +08:00
commit adf0d17497
3085 changed files with 456962 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
from gradio_client.client import Client
from gradio_client.data_classes import FileData
from gradio_client.utils import __version__, file, handle_file
__all__ = [
"Client",
"file",
"handle_file",
"FileData",
"__version__",
]
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,28 @@
from __future__ import annotations
from typing import Any, TypedDict
from typing_extensions import NotRequired
class FileData(TypedDict):
name: str | None # filename
data: str | None # base64 encoded data
size: NotRequired[int | None] # size in bytes
is_file: NotRequired[
bool
] # whether the data corresponds to a file or base64 encoded data
orig_name: NotRequired[str] # original filename
mime_type: NotRequired[str]
is_stream: NotRequired[bool]
class ParameterInfo(TypedDict):
label: str
parameter_name: str
parameter_has_default: NotRequired[bool]
parameter_default: NotRequired[Any]
type: dict
python_type: dict
component: str
example_input: Any
@@ -0,0 +1,371 @@
"""Contains methods that generate documentation for Gradio functions and classes."""
from __future__ import annotations
import dataclasses
import inspect
import warnings
from collections import defaultdict
from collections.abc import Callable
from functools import lru_cache
classes_to_document = defaultdict(list)
classes_inherit_documentation = {}
def set_documentation_group(m): # noqa: ARG001
"""A no-op for backwards compatibility of custom components published prior to 4.16.0"""
pass
def extract_instance_attr_doc(cls, attr):
code = inspect.getsource(cls.__init__)
lines = [line.strip() for line in code.split("\n")]
i = None
for i, line in enumerate(lines): # noqa: B007
if line.startswith("self." + attr + ":") or line.startswith(
"self." + attr + " ="
):
break
if i is None:
raise NameError(f"Could not find {attr} in {cls.__name__}")
start_line = lines.index('"""', i)
end_line = lines.index('"""', start_line + 1)
for j in range(i + 1, start_line):
if lines[j].startswith("self."):
raise ValueError(
f"Found another attribute before docstring for {attr} in {cls.__name__}: "
+ lines[j]
+ "\n start:"
+ lines[i]
)
doc_string = " ".join(lines[start_line + 1 : end_line])
return doc_string
_module_prefixes = [
("gradio._simple_templates", "component"),
("gradio.server", "block"),
("gradio.block", "block"),
("gradio.chat", "chatinterface"),
("gradio.component", "component"),
("gradio.events", "helpers"),
("gradio.data_classes", "helpers"),
("gradio.exceptions", "helpers"),
("gradio.external", "helpers"),
("gradio.flag", "flagging"),
("gradio.helpers", "helpers"),
("gradio.interface", "interface"),
("gradio.layout", "layout"),
("gradio.route", "routes"),
("gradio.theme", "themes"),
("gradio_client.", "py-client"),
("gradio.utils", "helpers"),
("gradio.renderable", "renderable"),
("gradio.validators", "validators"),
("gradio.caching", "helpers"),
]
@lru_cache(maxsize=10)
def _get_module_documentation_group(modname) -> str:
for prefix, group in _module_prefixes:
if modname.startswith(prefix):
return group
raise ValueError(f"No known documentation group for module {modname!r}")
def document(*fns, inherit=False, documentation_group=None):
"""
Defines the @document decorator which adds classes or functions to the Gradio
documentation at www.gradio.app/docs.
Usage examples:
- Put @document() above a class to document the class and its constructor.
- Put @document("fn1", "fn2") above a class to also document methods fn1 and fn2.
- Put @document("*fn3") with an asterisk above a class to document the instance attribute methods f3.
"""
_documentation_group = documentation_group
def inner_doc(cls):
functions = list(fns)
if hasattr(cls, "EVENTS"):
functions += cls.EVENTS
if inherit:
classes_inherit_documentation[cls] = None
documentation_group = _documentation_group # avoid `nonlocal` reassignment
if _documentation_group is None:
try:
modname = inspect.getmodule(cls).__name__ # type: ignore
if modname.startswith("gradio.") or modname.startswith(
"gradio_client."
):
documentation_group = _get_module_documentation_group(modname)
else:
# Then this is likely a custom Gradio component that we do not include in the documentation
pass
except Exception as exc:
warnings.warn(f"Could not get documentation group for {cls}: {exc}")
classes_to_document[documentation_group].append((cls, functions))
return cls
return inner_doc
def document_fn(fn: Callable, cls) -> tuple[str, list[dict], dict, str | None]:
"""
Generates documentation for any function.
Parameters:
fn: Function to document
Returns:
description: General description of fn
parameters: A list of dicts for each parameter, storing data for the parameter name, annotation and doc
return: A dict storing data for the returned annotation and doc
example: Code for an example use of the fn
"""
doc_str = inspect.getdoc(fn) or ""
doc_lines = doc_str.split("\n")
signature = inspect.signature(fn)
description, parameters, returns, examples = [], {}, [], []
mode = "description"
current_parameter = None
base_indent = None
for line in doc_lines:
line = line.rstrip()
if line == "Parameters:":
mode = "parameter"
base_indent = None
elif line.startswith("Example:"):
mode = "example"
base_indent = None
if "(" in line and ")" in line:
c = line.split("(")[1].split(")")[0]
if c != cls.__name__:
mode = "ignore"
elif line == "Returns:":
mode = "return"
base_indent = None
else:
if mode == "description":
description.append(line if line.strip() else "<br>")
continue
if not (line.startswith(" ") or line.strip() == ""):
print(line)
if not (line.startswith(" ") or line.strip() == ""):
raise SyntaxError(
f"Documentation format for {fn.__name__} has format error in line: {line}"
)
line = line[4:]
if mode == "parameter":
if ": " in line and not line.startswith(" "):
colon_index = line.index(": ")
if colon_index < -1:
raise SyntaxError(
f"Documentation format for {fn.__name__} has format error in line: {line}"
)
current_parameter = line[:colon_index]
parameter_doc = line[colon_index + 2 :]
parameters[current_parameter] = parameter_doc
base_indent = None
elif current_parameter and line.strip():
if base_indent is None:
base_indent = len(line) - len(line.lstrip())
if base_indent > 0 and line.startswith(" " * base_indent):
line = line[base_indent:]
parameters[current_parameter] += "\n" + line
elif mode == "return":
returns.append(line)
elif mode == "example":
examples.append(line)
description_doc = " ".join(description)
parameter_docs = []
for param_name, param in signature.parameters.items():
if param_name.startswith("_"):
continue
if param_name == "self":
continue
if param_name in ["kwargs", "args"] and param_name not in parameters:
continue
parameter_doc = {
"name": param_name,
"annotation": param.annotation,
"doc": parameters.get(param_name),
}
if param_name in parameters:
del parameters[param_name]
if param.default != inspect.Parameter.empty:
default = param.default
if isinstance(default, str):
default = '"' + default + '"'
if default.__class__.__module__ != "builtins":
default = f"{default.__class__.__name__}()"
parameter_doc["default"] = default
elif parameter_doc["doc"] is not None:
if "kwargs" in parameter_doc["doc"]:
parameter_doc["kwargs"] = True
if "args" in parameter_doc["doc"]:
parameter_doc["args"] = True
parameter_docs.append(parameter_doc)
if parameters:
raise ValueError(
f"Documentation format for {fn.__name__} documents "
f"nonexistent parameters: {', '.join(parameters.keys())}. "
f"Valid parameters: {', '.join(signature.parameters.keys())}"
)
if len(returns) == 0:
return_docs = {}
else:
return_doc_text = "\n".join(returns)
return_docs = {
"annotation": signature.return_annotation,
"doc": return_doc_text,
}
examples_doc = "\n".join(examples) if len(examples) > 0 else None
return description_doc, parameter_docs, return_docs, examples_doc
def document_cls(cls):
doc_str = inspect.getdoc(cls)
if doc_str is None:
return "", {}, ""
tags = {}
description_lines = []
mode = "description"
for line in doc_str.split("\n"):
line = line.rstrip()
if line.endswith(":") and " " not in line:
mode = line[:-1].lower()
tags[mode] = []
elif line.split(" ")[0].endswith(":") and not line.startswith(" "):
tag = line[: line.index(":")].lower()
value = line[line.index(":") + 2 :]
tags[tag] = value
elif mode == "description":
description_lines.append(line if line.strip() else "<br>")
else:
if not (line.startswith(" ") or not line.strip()):
raise SyntaxError(
f"Documentation format for {cls.__name__} has format error in line: {line}"
)
tags[mode].append(line[4:])
if "example" in tags:
example = "\n".join(tags["example"])
del tags["example"]
else:
example = None
for key, val in tags.items():
if isinstance(val, list):
tags[key] = "<br>".join(val)
description = " ".join(description_lines).replace("\n", "<br>")
return description, tags, example
def generate_documentation():
documentation = {}
for mode, class_list in classes_to_document.items():
documentation[mode] = []
for cls, fns in class_list:
fn_to_document = (
cls
if inspect.isfunction(cls) or dataclasses.is_dataclass(cls)
else cls.__init__
)
_, parameter_doc, return_doc, _ = document_fn(fn_to_document, cls)
if (
hasattr(cls, "preprocess")
and callable(cls.preprocess) # type: ignore
and hasattr(cls, "postprocess")
and callable(cls.postprocess) # type: ignore
):
preprocess_doc = document_fn(cls.preprocess, cls) # type: ignore
postprocess_doc = document_fn(cls.postprocess, cls) # type: ignore
preprocess_doc, postprocess_doc = (
{
"parameter_doc": preprocess_doc[1],
"return_doc": preprocess_doc[2],
},
{
"parameter_doc": postprocess_doc[1],
"return_doc": postprocess_doc[2],
},
)
cls_description, cls_tags, cls_example = document_cls(cls)
cls_documentation = {
"class": cls,
"name": cls.__name__,
"description": cls_description,
"tags": cls_tags,
"parameters": parameter_doc,
"returns": return_doc,
"example": cls_example,
"fns": [],
}
if (
hasattr(cls, "preprocess")
and callable(cls.preprocess) # type: ignore
and hasattr(cls, "postprocess")
and callable(cls.postprocess) # type: ignore
):
cls_documentation["preprocess"] = preprocess_doc # type: ignore
cls_documentation["postprocess"] = postprocess_doc # type: ignore
for fn_name in fns:
instance_attribute_fn = fn_name.startswith("*")
if instance_attribute_fn:
fn_name = fn_name[1:]
# Instance attribute fns are classes
# whose __call__ method determines their behavior
fn = getattr(cls(), fn_name).__call__
else:
fn = getattr(cls, fn_name)
if not callable(fn):
description_doc = str(fn)
parameter_docs = {}
return_docs = {}
examples_doc = ""
override_signature = f"gr.{cls.__name__}.{fn_name}"
else:
(
description_doc,
parameter_docs,
return_docs,
examples_doc,
) = document_fn(fn, cls)
if fn_name in getattr(cls, "EVENTS", []):
parameter_docs = parameter_docs[1:]
override_signature = None
if instance_attribute_fn:
description_doc = extract_instance_attr_doc(cls, fn_name)
cls_documentation["fns"].append(
{
"fn": fn,
"name": fn_name,
"description": description_doc,
"tags": {},
"parameters": parameter_docs,
"returns": return_docs,
"example": examples_doc,
"override_signature": override_signature,
}
)
documentation[mode].append(cls_documentation)
if cls in classes_inherit_documentation:
classes_inherit_documentation[cls] = cls_documentation["fns"]
for mode, class_list in classes_to_document.items():
for i, (cls, _) in enumerate(class_list):
for super_class, fns in classes_inherit_documentation.items():
if (
inspect.isclass(cls)
and issubclass(cls, super_class)
and cls != super_class
):
for inherited_fn in fns:
inherited_fn = dict(inherited_fn)
try:
inherited_fn["description"] = extract_instance_attr_doc(
cls, inherited_fn["name"]
)
except ValueError:
pass
documentation[mode][i]["fns"].append(inherited_fn)
return documentation
+43
View File
@@ -0,0 +1,43 @@
class SerializationSetupError(ValueError):
"""Raised when a serializers cannot be set up correctly."""
pass
class AuthenticationError(ValueError):
"""Raised when the client is unable to authenticate itself to a Gradio app due to invalid or missing credentials."""
pass
class ValidationError(ValueError):
"""Raised when the data that is passed into the Gradio app fails developer-defined validation."""
pass
class AppError(ValueError):
"""Raised when the upstream Gradio app throws an error because of the value submitted by the client."""
def __init__(
self,
message: str = "Error raised.",
duration: float | None = 10,
visible: bool = True,
title: str = "Error",
print_exception: bool = True,
):
"""
Parameters:
message: The error message to be displayed to the user. Can be HTML, which will be rendered in the modal.
duration: The duration in seconds to display the error message. If None or 0, the error message will be displayed until the user closes it.
visible: Whether the error message should be displayed in the UI.
title: The title to be displayed to the user at the top of the error modal.
print_exception: Whether to print traceback of the error to the console when the error is raised.
"""
self.title = title
self.message = message
self.duration = duration
self.visible = visible
self.print_exception = print_exception
super().__init__(self.message)
+8
View File
@@ -0,0 +1,8 @@
{
"name": "gradio_client",
"version": "2.5.0",
"description": "",
"python": "true",
"main_changeset": true,
"private": true
}
+276
View File
@@ -0,0 +1,276 @@
"""Centralized code snippet generation for Gradio API endpoints. Generates Python, JavaScript, and cURL code snippets from API info dicts."""
import copy
import json
import re
from typing import Any
BLOB_COMPONENTS = {
"Audio",
"DownloadButton",
"File",
"Image",
"ImageSlider",
"Model3D",
"UploadButton",
"Video",
}
def _is_file_data(obj: Any) -> bool:
return (
isinstance(obj, dict)
and "url" in obj
and obj.get("url")
and "meta" in obj
and isinstance(obj.get("meta"), dict)
and obj["meta"].get("_type") == "gradio.FileData"
)
def _has_file_data(obj: Any) -> bool:
if isinstance(obj, dict):
if _is_file_data(obj):
return True
return any(_has_file_data(v) for v in obj.values())
if isinstance(obj, (list, tuple)):
return any(_has_file_data(item) for item in obj)
return False
def _replace_file_data_py(obj: Any) -> Any:
if isinstance(obj, dict) and _is_file_data(obj):
return f"handle_file('{obj['url']}')"
if isinstance(obj, (list, tuple)):
return [_replace_file_data_py(item) for item in obj]
if isinstance(obj, dict):
return {k: _replace_file_data_py(v) for k, v in obj.items()}
return obj
def _simplify_file_data(obj: Any) -> Any:
if isinstance(obj, dict) and _is_file_data(obj):
return {"path": obj["url"], "meta": {"_type": "gradio.FileData"}}
if isinstance(obj, (list, tuple)):
return [_simplify_file_data(item) for item in obj]
if isinstance(obj, dict):
return {k: _simplify_file_data(v) for k, v in obj.items()}
return obj
_UNQUOTED = "UNQUOTED_GRADIO_"
def _stringify_py(obj: Any) -> str:
def _prepare(o: Any) -> Any:
if o is None:
return f"{_UNQUOTED}None"
if isinstance(o, bool):
return f"{_UNQUOTED}True" if o else f"{_UNQUOTED}False"
if isinstance(o, str) and o.startswith("handle_file(") and o.endswith(")"):
return f"{_UNQUOTED}{o}"
if isinstance(o, (list, tuple)):
return [_prepare(item) for item in o]
if isinstance(o, dict):
return {k: _prepare(v) for k, v in o.items()}
return o
prepared = _prepare(obj)
result = json.dumps(prepared, default=str)
result = re.sub(
rf'"{_UNQUOTED}(handle_file\([^)]*\))"',
r"\1",
result,
)
result = result.replace(f'"{_UNQUOTED}None"', "None")
result = result.replace(f'"{_UNQUOTED}True"', "True")
result = result.replace(f'"{_UNQUOTED}False"', "False")
return result
def _represent_value(value: Any, python_type: str | None, lang: str) -> str:
if python_type is None:
return "None" if lang == "py" else "null"
if value is None:
return "None" if lang == "py" else "null"
if python_type in ("string", "str"):
return f'"{value}"'
if python_type == "number":
return str(value)
if python_type in ("boolean", "bool"):
if lang == "py":
return "True" if value else "False"
return str(value).lower() if isinstance(value, bool) else str(value)
if python_type == "List[str]":
return json.dumps(value)
if python_type.startswith("Literal['"):
return f'"{value}"'
if isinstance(value, str):
if value == "":
return "None" if lang == "py" else "null"
return value
value = copy.deepcopy(value)
if lang == "bash":
value = _simplify_file_data(value)
if lang == "py":
value = _replace_file_data_py(value)
return _stringify_py(value)
def _get_param_value(param: dict) -> Any:
if param.get("parameter_has_default"):
return param.get("parameter_default")
return param.get("example_input")
def generate_python_snippet(
api_name: str,
params: list[dict],
src: str,
) -> str:
has_file = any(_has_file_data(p.get("example_input")) for p in params)
imports = "from gradio_client import Client"
if has_file:
imports += ", handle_file"
lines = [imports, ""]
lines.append(f'client = Client("{src}")')
predict_args = []
for p in params:
name = p.get("parameter_name") or p.get("label", "input")
value = _get_param_value(p)
ptype = p.get("python_type", {}).get("type")
formatted = _represent_value(value, ptype, "py")
predict_args.append(f"\t{name}={formatted},")
lines.append("result = client.predict(")
lines.extend(predict_args)
lines.append(f'\tapi_name="{api_name}",')
lines.append(")")
lines.append("print(result)")
return "\n".join(lines)
def generate_js_snippet(
api_name: str,
params: list[dict],
src: str,
) -> str:
blob_params = [p for p in params if p.get("component") in BLOB_COMPONENTS]
lines = ['import { Client } from "@gradio/client";', ""]
for i, bp in enumerate(blob_params):
example = bp.get("example_input", {})
url = example.get("url", "") if isinstance(example, dict) else ""
component = bp.get("component", "")
lines.append(f'const response_{i} = await fetch("{url}");')
lines.append(f"const example{component} = await response_{i}.blob();")
if blob_params:
lines.append("")
lines.append(f'const client = await Client.connect("{src}");')
blob_component_names = {bp.get("component") for bp in blob_params}
predict_args = []
for p in params:
name = p.get("parameter_name") or p.get("label", "input")
component = p.get("component", "")
if component in blob_component_names:
predict_args.append(f"\t\t{name}: example{component},")
else:
value = _get_param_value(p)
ptype = p.get("python_type", {}).get("type")
formatted = _represent_value(value, ptype, "js")
predict_args.append(f"\t\t{name}: {formatted},")
lines.append(f'const result = await client.predict("{api_name}", {{')
lines.extend(predict_args)
lines.append("});")
lines.append("")
lines.append("console.log(result.data);")
return "\n".join(lines)
def generate_bash_snippet(
api_name: str,
params: list[dict],
root: str,
api_prefix: str = "/",
) -> str:
normalised_root = root.rstrip("/")
normalised_prefix = api_prefix if api_prefix else "/"
endpoint_name = api_name.lstrip("/")
has_file = any(_has_file_data(p.get("example_input")) for p in params)
upload_url = f"{normalised_root}{normalised_prefix}upload"
lines: list[str] = []
file_param_names: list[str] = []
if has_file:
for p in params:
if _has_file_data(p.get("example_input")):
name = p.get("parameter_name") or p.get("label", "input")
file_param_names.append(name)
lines.append(
f"FILE_PATH=$(curl -s -X POST {upload_url}"
" -F 'files=@/path/to/your/file'"
" | tr -d '[]\" ')"
)
lines.append("")
data_dict = {}
for p in params:
name = p.get("parameter_name") or p.get("label", "input")
if name in file_param_names:
data_dict[name] = "FILE_PATH_PLACEHOLDER"
else:
value = _get_param_value(p)
ptype = p.get("python_type", {}).get("type")
formatted = _represent_value(value, ptype, "bash")
data_dict[name] = formatted
data_entries = ", ".join(f'"{k}": {v}' for k, v in data_dict.items())
data_str = "{" + data_entries + "}"
for _ in file_param_names:
replacement = '{"path": "\'$FILE_PATH\'", "meta": {"_type": "gradio.FileData"}}'
data_str = data_str.replace("FILE_PATH_PLACEHOLDER", replacement)
base_url = f"{normalised_root}{normalised_prefix}call/v2/{endpoint_name}"
get_url = f"{normalised_root}{normalised_prefix}call/{endpoint_name}"
lines.extend(
[
f'curl -X POST {base_url} -s -H "Content-Type: application/json" \\',
f" -d '{data_str}' \\",
" | awk -F'\"' '{ print $4}' \\",
f" | read EVENT_ID; curl -N {get_url}/$EVENT_ID",
]
)
return "\n".join(lines)
def generate_code_snippets(
api_name: str,
endpoint_info: dict,
root: str,
space_id: str | None = None,
api_prefix: str = "/",
) -> dict[str, str]:
params = endpoint_info.get("parameters", [])
src = space_id or root
return {
"python": generate_python_snippet(api_name, params, src),
"javascript": generate_js_snippet(api_name, params, src),
"bash": generate_bash_snippet(api_name, params, root, api_prefix),
}
@@ -0,0 +1,192 @@
import asyncio
import os
import threading
from threading import Event
import discord
import gradio as gr
from discord import Permissions
from discord.ext import commands
from discord.utils import oauth_url
import gradio_client as grc
from gradio_client.utils import QueueError
event = Event()
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
async def wait(job):
while not job.done():
await asyncio.sleep(0.2)
def get_client(session: str | None = None) -> grc.Client:
client = grc.Client("<<app-src>>", token=os.getenv("HF_TOKEN"))
if session:
client.session_hash = session
return client
def truncate_response(response: str) -> str:
ending = "...\nTruncating response to 2000 characters due to discord api limits."
if len(response) > 2000:
return response[: 2000 - len(ending)] + ending
else:
return response
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="/", intents=intents)
@bot.event
async def on_ready():
print(f"Logged in as {bot.user} (ID: {bot.user.id})")
synced = await bot.tree.sync()
print(f"Synced commands: {', '.join([s.name for s in synced])}.")
event.set()
print("------")
thread_to_client = {}
thread_to_user = {}
@bot.hybrid_command(
name="<<command-name>>",
description="Enter some text to chat with the bot! Like this: /<<command-name>> Hello, how are you?",
)
async def chat(ctx, prompt: str):
if ctx.author.id == bot.user.id:
return
try:
message = await ctx.send("Creating thread...")
thread = await message.create_thread(name=prompt)
loop = asyncio.get_running_loop()
client = await loop.run_in_executor(None, get_client, None)
job = client.submit(prompt, api_name="/<<api-name>>")
await wait(job)
try:
job.result()
response = job.outputs()[-1]
await thread.send(truncate_response(response))
thread_to_client[thread.id] = client
thread_to_user[thread.id] = ctx.author.id
except QueueError:
await thread.send(
"The gradio space powering this bot is really busy! Please try again later!"
)
except Exception as e:
print(f"{e}")
async def continue_chat(message):
"""Continues a given conversation based on chathistory"""
try:
client = thread_to_client[message.channel.id]
prompt = message.content
job = client.submit(prompt, api_name="/<<api-name>>")
await wait(job)
try:
job.result()
response = job.outputs()[-1]
await message.reply(truncate_response(response))
except QueueError:
await message.reply(
"The gradio space powering this bot is really busy! Please try again later!"
)
except Exception as e:
print(f"Error: {e}")
@bot.event
async def on_message(message):
"""Continue the chat"""
try:
if not message.author.bot:
if message.channel.id in thread_to_user:
if thread_to_user[message.channel.id] == message.author.id:
await continue_chat(message)
else:
await bot.process_commands(message)
except Exception as e:
print(f"Error: {e}")
# running in thread
def run_bot():
if not DISCORD_TOKEN:
print("DISCORD_TOKEN NOT SET")
event.set()
else:
bot.run(DISCORD_TOKEN)
threading.Thread(target=run_bot).start()
event.wait()
if not DISCORD_TOKEN:
welcome_message = """
## You have not specified a DISCORD_TOKEN, which means you have not created a bot account. Please follow these steps:
### 1. Go to https://discord.com/developers/applications and click 'New Application'
### 2. Give your bot a name 🤖
![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/BotName.png)
## 3. In Settings > Bot, click the 'Reset Token' button to get a new token. Write it down and keep it safe 🔐
![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/ResetToken.png)
## 4. Optionally make the bot public if you want anyone to be able to add it to their servers
## 5. Scroll down and enable 'Message Content Intent' under 'Priviledged Gateway Intents'
![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/MessageContentIntent.png)
## 6. Save your changes!
## 7. The token from step 3 is the DISCORD_TOKEN. Rerun the deploy_discord command, e.g client.deploy_discord(discord_bot_token=DISCORD_TOKEN, ...), or add the token as a space secret manually.
"""
else:
permissions = Permissions(326417525824)
url = oauth_url(bot.user.id, permissions=permissions)
welcome_message = f"""
## Add this bot to your server by clicking this link:
{url}
## How to use it?
The bot can be triggered via `/<<command-name>>` followed by your text prompt.
This will create a thread with the bot's response to your text prompt.
You can reply in the thread (without `/<<command-name>>`) to continue the conversation.
In the thread, the bot will only reply to the original author of the command.
⚠️ Note ⚠️: Please make sure this bot's command does have the same name as another command in your server.
⚠️ Note ⚠️: Bot commands do not work in DMs with the bot as of now.
"""
with gr.Blocks() as demo:
gr.Markdown(
f"""
# Discord bot of <<app-src>>
{welcome_message}
"""
)
demo.launch()
+199
View File
@@ -0,0 +1,199 @@
{
"SimpleSerializable": {
"type": {},
"description": "any valid value"
},
"StringSerializable": {
"type": "string"
},
"ListStringSerializable": {
"type": "array",
"items": {
"type": "string"
}
},
"BooleanSerializable": {
"type": "boolean"
},
"NumberSerializable": {
"type": "number"
},
"ImgSerializable": {
"type": "string",
"description": "base64 representation of an image"
},
"FileSerializable": {
"oneOf": [
{
"type": "string",
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "name of file" },
"data": {
"type": "string",
"description": "base64 representation of file"
},
"size": {
"type": "integer",
"description": "size of image in bytes"
},
"is_file": {
"type": "boolean",
"description": "true if the file has been uploaded to the server"
},
"orig_name": {
"type": "string",
"description": "original name of the file"
}
},
"required": ["name", "data"]
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "name of file" },
"data": {
"type": "string",
"description": "base64 representation of file"
},
"size": {
"type": "integer",
"description": "size of image in bytes"
},
"is_file": {
"type": "boolean",
"description": "true if the file has been uploaded to the server"
},
"orig_name": {
"type": "string",
"description": "original name of the file"
}
},
"required": ["name", "data"]
}
]
}
}
]
},
"SingleFileSerializable": {
"oneOf": [
{
"type": "string",
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "name of file" },
"data": {
"type": "string",
"description": "base64 representation of file"
},
"size": {
"type": "integer",
"description": "size of image in bytes"
},
"is_file": {
"type": "boolean",
"description": "true if the file has been uploaded to the server"
},
"orig_name": {
"type": "string",
"description": "original name of the file"
}
},
"required": ["name", "data"]
}
]
},
"MultipleFileSerializable": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"description": "filepath on your computer (or URL) of file"
},
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "name of file" },
"data": {
"type": "string",
"description": "base64 representation of file"
},
"size": {
"type": "integer",
"description": "size of image in bytes"
},
"is_file": {
"type": "boolean",
"description": "true if the file has been uploaded to the server"
},
"orig_name": {
"type": "string",
"description": "original name of the file"
}
},
"required": ["name", "data"]
}
]
}
},
"JSONSerializable": {
"type": {},
"description": "any valid json"
},
"GallerySerializable": {
"type": "array",
"items": {
"type": "array",
"items": false,
"maxSize": 2,
"minSize": 2,
"prefixItems": [
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "name of file" },
"data": {
"type": "string",
"description": "base64 representation of file"
},
"size": {
"type": "integer",
"description": "size of image in bytes"
},
"is_file": {
"type": "boolean",
"description": "true if the file has been uploaded to the server"
},
"orig_name": {
"type": "string",
"description": "original name of the file"
}
},
"required": ["name", "data"]
},
{
"oneOf": [
{ "type": "string", "description": "caption of image" },
{ "type": "null" }
]
}
]
}
}
}
File diff suppressed because it is too large Load Diff