yaju-bot 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,43 @@
1
+ Metadata-Version: 2.4
2
+ Name: yaju-bot
3
+ Version: 0.1.0
4
+ Summary: Go-powered Discord conversation intruder bot with a Python launcher
5
+ Author: dtmpm3485
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dtmpm3485/yaju-bot
8
+ Project-URL: Repository, https://github.com/dtmpm3485/yaju-bot
9
+ Keywords: discord,bot,go,python,meme
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Go
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+
16
+ # yaju-bot
17
+
18
+ Discordの会話にたまに返信で乱入するBotです。特定キーワードやメンションでも呼べます。
19
+
20
+ ## インストール
21
+
22
+ ```bash
23
+ pip install yaju-bot
24
+ ```
25
+
26
+ ## 使い方
27
+
28
+ ```python
29
+ from yaju_bot import run
30
+
31
+ run("DISCORD_BOT_TOKEN")
32
+ ```
33
+
34
+ ## 主なコマンド
35
+
36
+ - `/yaju on` / `/yaju off`
37
+ - `/yaju status` / `/yaju stats`
38
+ - `/yaju quote` / `/yaju test`
39
+ - `/yaju mode` / `/yaju chance` / `/yaju cooldown`
40
+ - `/yaju keyword add|remove|list|reset`
41
+ - `/yaju channel add|remove|list|clear`
42
+
43
+ 初期呼び出しワード: `野獣先輩` `やじゅ` `やじゅせん` `yaju` `yajuu` `114514` `810` `淫夢`
@@ -0,0 +1,28 @@
1
+ # yaju-bot
2
+
3
+ Discordの会話にたまに返信で乱入するBotです。特定キーワードやメンションでも呼べます。
4
+
5
+ ## インストール
6
+
7
+ ```bash
8
+ pip install yaju-bot
9
+ ```
10
+
11
+ ## 使い方
12
+
13
+ ```python
14
+ from yaju_bot import run
15
+
16
+ run("DISCORD_BOT_TOKEN")
17
+ ```
18
+
19
+ ## 主なコマンド
20
+
21
+ - `/yaju on` / `/yaju off`
22
+ - `/yaju status` / `/yaju stats`
23
+ - `/yaju quote` / `/yaju test`
24
+ - `/yaju mode` / `/yaju chance` / `/yaju cooldown`
25
+ - `/yaju keyword add|remove|list|reset`
26
+ - `/yaju channel add|remove|list|clear`
27
+
28
+ 初期呼び出しワード: `野獣先輩` `やじゅ` `やじゅせん` `yaju` `yajuu` `114514` `810` `淫夢`
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["setuptools>=75", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "yaju-bot"
7
+ version = "0.1.0"
8
+ description = "Go-powered Discord conversation intruder bot with a Python launcher"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "MIT"}
12
+ authors = [{name = "dtmpm3485"}]
13
+ keywords = ["discord", "bot", "go", "python", "meme"]
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "Programming Language :: Go",
17
+ "Operating System :: OS Independent"
18
+ ]
19
+
20
+ [project.urls]
21
+ Homepage = "https://github.com/dtmpm3485/yaju-bot"
22
+ Repository = "https://github.com/dtmpm3485/yaju-bot"
23
+
24
+ [tool.setuptools]
25
+ package-dir = {"" = "python"}
26
+ include-package-data = true
27
+
28
+ [tool.setuptools.packages.find]
29
+ where = ["python"]
30
+ include = ["yaju_bot*", "yajuu_bot*"]
@@ -0,0 +1,203 @@
1
+ """Python launcher for the Go-powered yaju-bot."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import os
7
+ import platform
8
+ import shutil
9
+ import stat
10
+ import subprocess
11
+ import sys
12
+ import tarfile
13
+ import tempfile
14
+ import urllib.error
15
+ import urllib.request
16
+ import zipfile
17
+ from importlib.metadata import PackageNotFoundError, version
18
+ from pathlib import Path
19
+ from typing import Optional
20
+
21
+ __all__ = ["run"]
22
+
23
+ _PACKAGE = "yaju-bot"
24
+ _REPO = "dtmpm3485/yaju-bot"
25
+ _FALLBACK_VERSION = "0.1.0"
26
+
27
+ try:
28
+ __version__ = version(_PACKAGE)
29
+ except PackageNotFoundError:
30
+ __version__ = _FALLBACK_VERSION
31
+
32
+
33
+ def _cache_root() -> Path:
34
+ override = os.environ.get("YAJU_BOT_CACHE")
35
+ if override:
36
+ return Path(override).expanduser()
37
+ if os.name == "nt" and os.environ.get("LOCALAPPDATA"):
38
+ return Path(os.environ["LOCALAPPDATA"]) / "yaju-bot" / "cache"
39
+ xdg = os.environ.get("XDG_CACHE_HOME")
40
+ if xdg:
41
+ return Path(xdg) / "yaju-bot"
42
+ return Path.home() / ".cache" / "yaju-bot"
43
+
44
+
45
+ def _platform_asset_for(system: str, machine: str) -> tuple[str, str]:
46
+ system = system.lower()
47
+ machine = machine.lower()
48
+ arch_map = {
49
+ "x86_64": "amd64",
50
+ "amd64": "amd64",
51
+ "aarch64": "arm64",
52
+ "arm64": "arm64",
53
+ "armv7l": "armv7",
54
+ "armv7": "armv7",
55
+ }
56
+ arch = arch_map.get(machine)
57
+ if arch is None:
58
+ raise RuntimeError(f"unsupported CPU architecture: {machine}")
59
+
60
+ if system == "linux":
61
+ os_name = "linux"
62
+ ext = ".tar.gz"
63
+ elif system == "darwin":
64
+ if arch == "armv7":
65
+ raise RuntimeError("unsupported macOS architecture: armv7")
66
+ os_name = "darwin"
67
+ ext = ".tar.gz"
68
+ elif system == "windows":
69
+ if arch == "armv7":
70
+ raise RuntimeError("unsupported Windows architecture: armv7")
71
+ os_name = "windows"
72
+ ext = ".zip"
73
+ else:
74
+ raise RuntimeError(f"unsupported operating system: {system}")
75
+
76
+ return f"yaju-bot-{os_name}-{arch}{ext}", "yaju-bot.exe" if os_name == "windows" else "yaju-bot"
77
+
78
+
79
+ def _platform_asset() -> tuple[str, str]:
80
+ return _platform_asset_for(platform.system(), platform.machine())
81
+
82
+
83
+ def _request_bytes(url: str) -> bytes:
84
+ request = urllib.request.Request(url, headers={"User-Agent": f"yaju-bot/{__version__}"})
85
+ with urllib.request.urlopen(request, timeout=30) as response:
86
+ return response.read()
87
+
88
+
89
+ def _expected_checksum(checksums: bytes, asset_name: str) -> str:
90
+ for raw_line in checksums.decode("utf-8").splitlines():
91
+ parts = raw_line.strip().split()
92
+ if len(parts) >= 2 and parts[-1].lstrip("*") == asset_name:
93
+ digest = parts[0].lower()
94
+ if len(digest) == 64 and all(ch in "0123456789abcdef" for ch in digest):
95
+ return digest
96
+ raise RuntimeError(f"checksum not found for release asset: {asset_name}")
97
+
98
+
99
+ def _download_release_binary() -> Path:
100
+ asset_name, binary_name = _platform_asset()
101
+ cache_dir = _cache_root() / __version__
102
+ binary = cache_dir / binary_name
103
+ if binary.is_file():
104
+ return binary
105
+
106
+ tag = f"v{__version__}"
107
+ base = f"https://github.com/{_REPO}/releases/download/{tag}"
108
+ try:
109
+ checksums = _request_bytes(f"{base}/checksums.txt")
110
+ archive = _request_bytes(f"{base}/{asset_name}")
111
+ except (urllib.error.URLError, TimeoutError, OSError) as exc:
112
+ raise RuntimeError(f"failed to download yaju-bot {tag}: {exc}") from exc
113
+
114
+ expected = _expected_checksum(checksums, asset_name)
115
+ actual = hashlib.sha256(archive).hexdigest()
116
+ if actual != expected:
117
+ raise RuntimeError(f"release checksum mismatch for {asset_name}")
118
+
119
+ cache_dir.mkdir(parents=True, exist_ok=True)
120
+ with tempfile.TemporaryDirectory(prefix="yaju-bot-") as tmp_name:
121
+ tmp = Path(tmp_name)
122
+ archive_path = tmp / asset_name
123
+ archive_path.write_bytes(archive)
124
+ extracted = tmp / binary_name
125
+
126
+ if asset_name.endswith(".zip"):
127
+ with zipfile.ZipFile(archive_path) as zf:
128
+ try:
129
+ data = zf.read(binary_name)
130
+ except KeyError as exc:
131
+ raise RuntimeError(f"{binary_name} is missing from {asset_name}") from exc
132
+ extracted.write_bytes(data)
133
+ else:
134
+ with tarfile.open(archive_path, "r:gz") as tf:
135
+ try:
136
+ member = tf.getmember(binary_name)
137
+ except KeyError as exc:
138
+ raise RuntimeError(f"{binary_name} is missing from {asset_name}") from exc
139
+ source = tf.extractfile(member)
140
+ if source is None:
141
+ raise RuntimeError(f"failed to read {binary_name} from {asset_name}")
142
+ extracted.write_bytes(source.read())
143
+
144
+ staged = cache_dir / f".{binary_name}.{os.getpid()}.tmp"
145
+ try:
146
+ shutil.copyfile(extracted, staged)
147
+ if os.name != "nt":
148
+ staged.chmod(staged.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
149
+ os.replace(staged, binary)
150
+ finally:
151
+ try:
152
+ staged.unlink()
153
+ except FileNotFoundError:
154
+ pass
155
+
156
+ return binary
157
+
158
+
159
+ def _source_checkout() -> Optional[Path]:
160
+ here = Path(__file__).resolve()
161
+ for parent in here.parents:
162
+ if (parent / "go.mod").is_file() and (parent / "cmd" / "yaju-bot").is_dir():
163
+ return parent
164
+ return None
165
+
166
+
167
+ def _resolve_command() -> tuple[list[str], Optional[str]]:
168
+ override = os.environ.get("YAJU_BOT_BIN")
169
+ if override:
170
+ return [override], None
171
+
172
+ source = _source_checkout()
173
+ go = shutil.which("go")
174
+ if source is not None and go is not None:
175
+ return [go, "run", "./cmd/yaju-bot"], str(source)
176
+
177
+ try:
178
+ return [str(_download_release_binary())], None
179
+ except RuntimeError as download_error:
180
+ if go is not None:
181
+ return [go, "run", f"github.com/{_REPO}/cmd/yaju-bot@v{__version__}"], None
182
+ raise RuntimeError(
183
+ f"{download_error}. Install Go as a fallback, or set YAJU_BOT_BIN to a yaju-bot executable."
184
+ ) from download_error
185
+
186
+
187
+ def run(token: str, *, data_dir: str | os.PathLike[str] | None = None) -> None:
188
+ """Start yaju-bot and block until it exits."""
189
+ if not isinstance(token, str) or not token.strip():
190
+ raise ValueError("token must be a non-empty Discord bot token")
191
+
192
+ env = os.environ.copy()
193
+ env["DISCORD_TOKEN"] = token.strip()
194
+ if data_dir is not None:
195
+ env["YAJU_DATA_DIR"] = os.fspath(data_dir)
196
+
197
+ command, cwd = _resolve_command()
198
+ try:
199
+ completed = subprocess.run(command, env=env, cwd=cwd, check=False)
200
+ except KeyboardInterrupt:
201
+ return
202
+ if completed.returncode != 0:
203
+ raise RuntimeError(f"yaju-bot exited with status {completed.returncode}")
@@ -0,0 +1,43 @@
1
+ Metadata-Version: 2.4
2
+ Name: yaju-bot
3
+ Version: 0.1.0
4
+ Summary: Go-powered Discord conversation intruder bot with a Python launcher
5
+ Author: dtmpm3485
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dtmpm3485/yaju-bot
8
+ Project-URL: Repository, https://github.com/dtmpm3485/yaju-bot
9
+ Keywords: discord,bot,go,python,meme
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Go
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+
16
+ # yaju-bot
17
+
18
+ Discordの会話にたまに返信で乱入するBotです。特定キーワードやメンションでも呼べます。
19
+
20
+ ## インストール
21
+
22
+ ```bash
23
+ pip install yaju-bot
24
+ ```
25
+
26
+ ## 使い方
27
+
28
+ ```python
29
+ from yaju_bot import run
30
+
31
+ run("DISCORD_BOT_TOKEN")
32
+ ```
33
+
34
+ ## 主なコマンド
35
+
36
+ - `/yaju on` / `/yaju off`
37
+ - `/yaju status` / `/yaju stats`
38
+ - `/yaju quote` / `/yaju test`
39
+ - `/yaju mode` / `/yaju chance` / `/yaju cooldown`
40
+ - `/yaju keyword add|remove|list|reset`
41
+ - `/yaju channel add|remove|list|clear`
42
+
43
+ 初期呼び出しワード: `野獣先輩` `やじゅ` `やじゅせん` `yaju` `yajuu` `114514` `810` `淫夢`
@@ -0,0 +1,8 @@
1
+ README.md
2
+ pyproject.toml
3
+ python/yaju_bot/__init__.py
4
+ python/yaju_bot.egg-info/PKG-INFO
5
+ python/yaju_bot.egg-info/SOURCES.txt
6
+ python/yaju_bot.egg-info/dependency_links.txt
7
+ python/yaju_bot.egg-info/top_level.txt
8
+ python/yajuu_bot/__init__.py
@@ -0,0 +1,2 @@
1
+ yaju_bot
2
+ yajuu_bot
@@ -0,0 +1,2 @@
1
+ from yaju_bot import * # noqa: F401,F403
2
+ from yaju_bot import __version__
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+