shindan-cli 1.3.0__tar.gz → 2.2.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,144 @@
1
+ cov.xml
2
+
3
+ # https://github.com/github/gitignore/blob/master/Python.gitignore
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
101
+ __pypackages__/
102
+
103
+ # Celery stuff
104
+ celerybeat-schedule
105
+ celerybeat.pid
106
+
107
+ # SageMath parsed files
108
+ *.sage.py
109
+
110
+ # Environments
111
+ .env
112
+ .venv
113
+ env/
114
+ venv/
115
+ ENV/
116
+ env.bak/
117
+ venv.bak/
118
+
119
+ # Spyder project settings
120
+ .spyderproject
121
+ .spyproject
122
+
123
+ # Rope project settings
124
+ .ropeproject
125
+
126
+ # mkdocs documentation
127
+ /site
128
+
129
+ # mypy
130
+ .mypy_cache/
131
+ .dmypy.json
132
+ dmypy.json
133
+
134
+ # Pyre type checker
135
+ .pyre/
136
+
137
+ # pytype static type analyzer
138
+ .pytype/
139
+
140
+ # Cython debug symbols
141
+ cython_debug/
142
+
143
+ # vscode
144
+ .vscode/
@@ -1,58 +1,49 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: shindan-cli
3
- Version: 1.3.0
3
+ Version: 2.2.0
4
4
  Summary: ShindanMaker (https://shindanmaker.com) CLI
5
- Home-page: https://github.com/eggplants/shindan-cli
5
+ Project-URL: Repository, https://github.com/eggplants/shindan-cli
6
+ Author-email: eggplants <w10776e8w@yahoo.co.jp>
6
7
  License: MIT
7
- Keywords: shindanmaker,cli
8
- Author: eggplants
9
- Author-email: w10776e8w@yahoo.co.jp
10
- Requires-Python: >=3.7,<4
8
+ License-File: LICENSE
9
+ Keywords: cli,shindanmaker
11
10
  Classifier: Development Status :: 3 - Alpha
12
11
  Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.7
15
- Classifier: Programming Language :: Python :: 3.8
16
- Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3 :: Only
17
13
  Classifier: Programming Language :: Python :: 3.10
18
14
  Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3 :: Only
20
- Requires-Dist: beautifulsoup4 (>=4.11.2,<5.0.0)
21
- Requires-Dist: lxml (>=4.9.2,<5.0.0)
22
- Requires-Dist: requests (>=2.28.2,<3.0.0)
23
- Project-URL: Repository, https://github.com/eggplants/shindan-cli
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: <4,>=3.10
20
+ Requires-Dist: beautifulsoup4<5,>=4.12.3
21
+ Requires-Dist: cloudscraper<2,>=1.2.71
22
+ Requires-Dist: lxml<7,>=5.3
23
+ Requires-Dist: requests<3,>=2.32.3
24
24
  Description-Content-Type: text/markdown
25
25
 
26
26
  # shindan-cli
27
27
 
28
- [![Release Package](
28
+ [![CI](
29
+ <https://github.com/eggplants/shindan-cli/actions/workflows/ci.yml/badge.svg>
30
+ )](
31
+ <https://github.com/eggplants/shindan-cli/actions/workflows/ci.yml>
32
+ ) [![Release Package](
29
33
  <https://github.com/eggplants/shindan-cli/actions/workflows/release.yml/badge.svg>
30
34
  )](
31
35
  <https://github.com/eggplants/shindan-cli/actions/workflows/release.yml>
32
36
  ) [![PyPI](
33
37
  <https://img.shields.io/pypi/v/shindan-cli?color=blue>
34
- ) ![PyPI - Python Version](
38
+ )](
39
+ <https://pypi.org/project/shindan-cli>
40
+ ) [![PyPI - Python Version](
35
41
  <https://img.shields.io/pypi/pyversions/shindan-cli>
36
- )
37
- ](
42
+ )](
38
43
  <https://pypi.org/project/shindan-cli>
39
44
  )
40
45
 
41
- [![Test](
42
- <https://github.com/eggplants/shindan-cli/actions/workflows/test.yml/badge.svg>
43
- )](
44
- <https://github.com/eggplants/shindan-cli/actions/workflows/test.yml>
45
- ) [![Maintainability](
46
- <https://api.codeclimate.com/v1/badges/9134b56a4241e91dfa01/maintainability>
47
- )](
48
- <https://codeclimate.com/github/eggplants/shindan-cli/maintainability>
49
- ) [![Test Coverage](
50
- <https://api.codeclimate.com/v1/badges/9134b56a4241e91dfa01/test_coverage>
51
- )](
52
- <https://codeclimate.com/github/eggplants/shindan-cli/test_coverage>
53
- )
54
-
55
- ShindanMaker (<https://shindanmaker.com>) CLI
46
+ ShindanMaker (診断メーカー, <https://shindanmaker.com>) CLI + Library
56
47
 
57
48
  ## Install
58
49
 
@@ -62,6 +53,13 @@ pip install shindan-cli
62
53
 
63
54
  ## Usage
64
55
 
56
+ Supported types of diagnosis:
57
+
58
+ - [Name-based diagnosis (名前診断)](https://shindanmaker.com/list/name)
59
+ - [Branching diagnosis (分岐診断)](https://shindanmaker.com/list/branch)
60
+ - [AI diagnosis (AI診断)](https://shindanmaker.com/list/ai)
61
+ - [Check Diagnosis (チェック診断)](https://shindanmaker.com/list/check)
62
+
65
63
  ### CLI
66
64
 
67
65
  ```shellsession
@@ -128,44 +126,43 @@ MIT
128
126
 
129
127
  - C#
130
128
  - [misodengaku/ShindanMaker](https://github.com/misodengaku/ShindanMaker)
131
- - Library
129
+ - Library (Unmaintained)
132
130
  - Go
133
131
  - [kakakaya/goshindan](https://github.com/kakakaya/goshindan)
134
- - Library + CLI
132
+ - Library + CLI (Archived)
135
133
  - <https://pkg.go.dev/github.com/kakakaya/goshindan>
136
134
  - Java
137
135
  - [shibafu528/shindan4j](https://github.com/shibafu528/shindan4j)
138
- - Library
136
+ - Library (Unmaintained)
139
137
  - <https://jitpack.io/#shibafu528/shindan4j>
140
138
  - JavaScript
141
139
  - [asawo/shindan-scraper](https://github.com/asawo/shindan-scraper)
142
- - Library
140
+ - Library (Unmaintained)
143
141
  - [stawberri/shindan](https://github.com/stawberri/shindan)
144
142
  - Library (Archived)
145
143
  - <https://www.npmjs.com/package/shindan>
146
144
  - Perl
147
145
  - [Likk/WebService-ShindanMaker](https://github.com/Likk/WebService-ShindanMaker)
148
- - Library
146
+ - Library (Unmaintained)
149
147
  - PHP
150
148
  - [moroya/php-shindanmaker](https://github.com/moroya/php-shindanmaker)
151
- - Library
149
+ - Library (Unmaintained)
152
150
  - <https://packagist.org/packages/moroya/php-shindanmaker>
153
151
  - Python
154
152
  - [Le96/auto_shindanmaker](https://github.com/Le96/auto_shindanmaker)
155
- - Bot Server
153
+ - Bot Server (Unmaintained)
156
154
  - [tanitanin/shindan-python](https://github.com/tanitanin/shindan-python)
157
- - CLI (Script)
155
+ - CLI (Unmaintained)
158
156
  - Ruby
159
157
  - [osak/shindanmaker](https://github.com/osak/shindanmaker)
160
- - [Mikutter](https://github.com/mikutter/mikutter) Plugin
158
+ - [Mikutter](https://github.com/mikutter/mikutter) Plugin (Unmaintained)
161
159
  - [gouf/shindan](https://github.com/gouf/shindan)
162
- - Library
160
+ - Library (Unmaintained)
163
161
  - [ikaruga777/shindan-cli](https://github.com/ikaruga777/shindan-cli)
164
- - CLI
162
+ - CLI (Unmaintained)
165
163
  - [yasuhito/shindan](https://github.com/yasuhito/shindan)
166
- - CLI
164
+ - CLI (Unmaintained)
167
165
  - <https://rubygems.org/gems/shindan>
168
166
  - TypeScript
169
167
  - [dqn/shindanmaker-js](https://github.com/dqn/shindanmaker-js)
170
- - Library
171
-
168
+ - Library (Archived)
@@ -1,33 +1,24 @@
1
1
  # shindan-cli
2
2
 
3
- [![Release Package](
3
+ [![CI](
4
+ <https://github.com/eggplants/shindan-cli/actions/workflows/ci.yml/badge.svg>
5
+ )](
6
+ <https://github.com/eggplants/shindan-cli/actions/workflows/ci.yml>
7
+ ) [![Release Package](
4
8
  <https://github.com/eggplants/shindan-cli/actions/workflows/release.yml/badge.svg>
5
9
  )](
6
10
  <https://github.com/eggplants/shindan-cli/actions/workflows/release.yml>
7
11
  ) [![PyPI](
8
12
  <https://img.shields.io/pypi/v/shindan-cli?color=blue>
9
- ) ![PyPI - Python Version](
13
+ )](
14
+ <https://pypi.org/project/shindan-cli>
15
+ ) [![PyPI - Python Version](
10
16
  <https://img.shields.io/pypi/pyversions/shindan-cli>
11
- )
12
- ](
17
+ )](
13
18
  <https://pypi.org/project/shindan-cli>
14
19
  )
15
20
 
16
- [![Test](
17
- <https://github.com/eggplants/shindan-cli/actions/workflows/test.yml/badge.svg>
18
- )](
19
- <https://github.com/eggplants/shindan-cli/actions/workflows/test.yml>
20
- ) [![Maintainability](
21
- <https://api.codeclimate.com/v1/badges/9134b56a4241e91dfa01/maintainability>
22
- )](
23
- <https://codeclimate.com/github/eggplants/shindan-cli/maintainability>
24
- ) [![Test Coverage](
25
- <https://api.codeclimate.com/v1/badges/9134b56a4241e91dfa01/test_coverage>
26
- )](
27
- <https://codeclimate.com/github/eggplants/shindan-cli/test_coverage>
28
- )
29
-
30
- ShindanMaker (<https://shindanmaker.com>) CLI
21
+ ShindanMaker (診断メーカー, <https://shindanmaker.com>) CLI + Library
31
22
 
32
23
  ## Install
33
24
 
@@ -37,6 +28,13 @@ pip install shindan-cli
37
28
 
38
29
  ## Usage
39
30
 
31
+ Supported types of diagnosis:
32
+
33
+ - [Name-based diagnosis (名前診断)](https://shindanmaker.com/list/name)
34
+ - [Branching diagnosis (分岐診断)](https://shindanmaker.com/list/branch)
35
+ - [AI diagnosis (AI診断)](https://shindanmaker.com/list/ai)
36
+ - [Check Diagnosis (チェック診断)](https://shindanmaker.com/list/check)
37
+
40
38
  ### CLI
41
39
 
42
40
  ```shellsession
@@ -103,43 +101,43 @@ MIT
103
101
 
104
102
  - C#
105
103
  - [misodengaku/ShindanMaker](https://github.com/misodengaku/ShindanMaker)
106
- - Library
104
+ - Library (Unmaintained)
107
105
  - Go
108
106
  - [kakakaya/goshindan](https://github.com/kakakaya/goshindan)
109
- - Library + CLI
107
+ - Library + CLI (Archived)
110
108
  - <https://pkg.go.dev/github.com/kakakaya/goshindan>
111
109
  - Java
112
110
  - [shibafu528/shindan4j](https://github.com/shibafu528/shindan4j)
113
- - Library
111
+ - Library (Unmaintained)
114
112
  - <https://jitpack.io/#shibafu528/shindan4j>
115
113
  - JavaScript
116
114
  - [asawo/shindan-scraper](https://github.com/asawo/shindan-scraper)
117
- - Library
115
+ - Library (Unmaintained)
118
116
  - [stawberri/shindan](https://github.com/stawberri/shindan)
119
117
  - Library (Archived)
120
118
  - <https://www.npmjs.com/package/shindan>
121
119
  - Perl
122
120
  - [Likk/WebService-ShindanMaker](https://github.com/Likk/WebService-ShindanMaker)
123
- - Library
121
+ - Library (Unmaintained)
124
122
  - PHP
125
123
  - [moroya/php-shindanmaker](https://github.com/moroya/php-shindanmaker)
126
- - Library
124
+ - Library (Unmaintained)
127
125
  - <https://packagist.org/packages/moroya/php-shindanmaker>
128
126
  - Python
129
127
  - [Le96/auto_shindanmaker](https://github.com/Le96/auto_shindanmaker)
130
- - Bot Server
128
+ - Bot Server (Unmaintained)
131
129
  - [tanitanin/shindan-python](https://github.com/tanitanin/shindan-python)
132
- - CLI (Script)
130
+ - CLI (Unmaintained)
133
131
  - Ruby
134
132
  - [osak/shindanmaker](https://github.com/osak/shindanmaker)
135
- - [Mikutter](https://github.com/mikutter/mikutter) Plugin
133
+ - [Mikutter](https://github.com/mikutter/mikutter) Plugin (Unmaintained)
136
134
  - [gouf/shindan](https://github.com/gouf/shindan)
137
- - Library
135
+ - Library (Unmaintained)
138
136
  - [ikaruga777/shindan-cli](https://github.com/ikaruga777/shindan-cli)
139
- - CLI
137
+ - CLI (Unmaintained)
140
138
  - [yasuhito/shindan](https://github.com/yasuhito/shindan)
141
- - CLI
139
+ - CLI (Unmaintained)
142
140
  - <https://rubygems.org/gems/shindan>
143
141
  - TypeScript
144
142
  - [dqn/shindanmaker-js](https://github.com/dqn/shindanmaker-js)
145
- - Library
143
+ - Library (Archived)
@@ -0,0 +1,86 @@
1
+ [build-system]
2
+ build-backend = "hatchling.build"
3
+
4
+ requires = [ "hatchling", "uv-dynamic-versioning" ]
5
+
6
+ [project]
7
+ name = "shindan-cli"
8
+ description = "ShindanMaker (https://shindanmaker.com) CLI"
9
+ readme = "README.md"
10
+ keywords = [
11
+ "cli",
12
+ "shindanmaker",
13
+ ]
14
+ license = { text = "MIT" }
15
+ authors = [ { name = "eggplants", email = "w10776e8w@yahoo.co.jp" } ]
16
+ requires-python = ">=3.10,<4"
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
26
+ "Typing :: Typed",
27
+ ]
28
+ dynamic = [ "version" ]
29
+ dependencies = [
30
+ "beautifulsoup4>=4.12.3,<5",
31
+ "cloudscraper>=1.2.71,<2",
32
+ "lxml>=5.3,<7",
33
+ "requests>=2.32.3,<3",
34
+ ]
35
+
36
+ urls.Repository = "https://github.com/eggplants/shindan-cli"
37
+ scripts.shindan = "shindan_cli.main:main"
38
+
39
+ [dependency-groups]
40
+ dev = [
41
+ "pymarkdownlnt>=0.9.33",
42
+ "pyproject-fmt>=2.11.1",
43
+ "pytest>=9.0.2",
44
+ "pytest-asyncio>=1.3",
45
+ "pytest-cov>=7",
46
+ ]
47
+ docs = [
48
+ "pdoc>=16",
49
+ ]
50
+
51
+ [tool.hatch.version]
52
+ source = "uv-dynamic-versioning"
53
+
54
+ [tool.hatch.build.targets.sdist]
55
+ include = [ "shindan_cli" ]
56
+
57
+ [tool.hatch.build.targets.wheel]
58
+ include = [ "shindan_cli" ]
59
+
60
+ [tool.uv]
61
+ preview = true
62
+ default-groups = [
63
+ "dev",
64
+ "docs",
65
+ ]
66
+ exclude-newer = "P7D"
67
+
68
+ [tool.ruff]
69
+ line-length = 120
70
+ format.indent-style = "space"
71
+ format.quote-style = "double"
72
+ lint.select = [ "ALL" ]
73
+ lint.ignore = [
74
+ "COM812",
75
+ "D203", # 1 blank line required before class docstring
76
+ "D213", # Multi-line docstring summary should start at the second line
77
+ ]
78
+ lint.per-file-ignores."tests/*.py" = [
79
+ "D",
80
+ "S101", # Use of assert detected
81
+ ]
82
+
83
+ [tool.uv-dynamic-versioning]
84
+ vcs = "git"
85
+ style = "semver"
86
+ fallback-version = "0.0.0"
@@ -0,0 +1,14 @@
1
+ """.. include:: ../README.md""" # noqa: D400, D415
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib.metadata
6
+
7
+ from .shindan import ShindanError, ShindanResult, shindan
8
+
9
+ try:
10
+ __version__ = importlib.metadata.version(__name__)
11
+ except importlib.metadata.PackageNotFoundError:
12
+ __version__ = "0.0.0"
13
+
14
+ __all__ = ("ShindanError", "ShindanResult", "shindan")
@@ -0,0 +1,66 @@
1
+ """Constants for the shindan CLI."""
2
+
3
+ from typing import Literal, TypedDict
4
+
5
+
6
+ class AIParams(TypedDict):
7
+ _token: str
8
+ randname: str
9
+ type: Literal["ai"]
10
+ shindan_token: str
11
+ encrypted_exec_key: str
12
+
13
+
14
+ class BranchParams(TypedDict):
15
+ _token: str
16
+ randname: str
17
+ hiddenName: str
18
+ type: Literal["branch"]
19
+ shindan_token: str
20
+ rbr: str
21
+
22
+
23
+ class CheckParams(TypedDict):
24
+ _token: str
25
+ randname: str
26
+ hiddenName: str
27
+ type: Literal["check"]
28
+ shindan_token: str
29
+ # input-check-choice[choice_id]: str
30
+
31
+
32
+ class NameParams(TypedDict):
33
+ _token: str
34
+ randname: str
35
+ hiddenName: str
36
+ type: Literal["name"]
37
+ shindan_token: str
38
+
39
+
40
+ class TargetKeysByType(TypedDict):
41
+ ai: AIParams
42
+ branch: BranchParams
43
+ check: CheckParams
44
+ name: NameParams
45
+
46
+
47
+ TARGET_KEYS_BY_TYPE = {
48
+ "ai": AIParams.__annotations__.keys(),
49
+ "branch": BranchParams.__annotations__.keys(),
50
+ "check": CheckParams.__annotations__.keys(),
51
+ "name": NameParams.__annotations__.keys(),
52
+ }
53
+
54
+ BASE_URL = "https://shindanmaker.com"
55
+
56
+ HEADERS = {
57
+ "User-Agent": (
58
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
59
+ ),
60
+ }
61
+
62
+ __all__ = (
63
+ "BASE_URL",
64
+ "HEADERS",
65
+ "TARGET_KEYS_BY_TYPE",
66
+ )
@@ -0,0 +1,185 @@
1
+ """Module contains functions to get the result from <https://shindanmaker.com>."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from typing import TYPE_CHECKING, Union
7
+
8
+ from bs4 import BeautifulSoup, Tag
9
+
10
+ from .constants import BASE_URL, HEADERS, AIParams, BranchParams, CheckParams, NameParams
11
+
12
+ if TYPE_CHECKING:
13
+ from requests import Session
14
+
15
+ from .models import ShindanResult, UserInputs
16
+
17
+ Params = Union[AIParams, BranchParams, CheckParams, NameParams]
18
+
19
+
20
+ def __get_result(
21
+ session: Session,
22
+ params: Params,
23
+ *,
24
+ is_renewal: bool = False,
25
+ shindan_url: str,
26
+ ) -> ShindanResult:
27
+ result_page = session.post(
28
+ shindan_url + ("/r" if is_renewal else ""),
29
+ data=params,
30
+ headers=HEADERS,
31
+ )
32
+ soup = BeautifulSoup(result_page.text, features="lxml")
33
+ result_tag = soup.find(id="share-copytext-shindanresult-textarea")
34
+
35
+ if not isinstance(result_tag, Tag) or not result_tag.text:
36
+ msg = f"Could not find a tag contains the result, returns: {result_tag}"
37
+ raise TypeError(msg)
38
+
39
+ *results, hashtag, shindan_url, _ = result_tag.text.split("\n")
40
+
41
+ if not results[-1]:
42
+ results.pop(-1)
43
+
44
+ return {
45
+ "results": results,
46
+ "hashtags": hashtag.split("\xa0"),
47
+ "shindan_url": shindan_url,
48
+ }
49
+
50
+
51
+ def get_result_by_ai(
52
+ session: Session,
53
+ params: AIParams,
54
+ *,
55
+ user_inputs: UserInputs,
56
+ hashtag: str | None,
57
+ shindan_url: str,
58
+ ) -> ShindanResult:
59
+ """Get result by AI type shindan.
60
+
61
+ Args:
62
+ session (Session): session object
63
+ params (Params): input parameters fetched from shindan page
64
+ user_inputs (UserInputs): user inputs
65
+ hashtag (str | None): hashtag
66
+ shindan_url (str): shindan url
67
+
68
+ Returns:
69
+ ShindanResult: the returned result from <https://shindanmaker.com>
70
+
71
+ """
72
+ res = session.post(
73
+ shindan_url,
74
+ data=params,
75
+ headers=HEADERS,
76
+ )
77
+ meta = BeautifulSoup(
78
+ res.text,
79
+ features="lxml",
80
+ ).select_one('meta[name="csrf-token"]')
81
+ if not res.ok or not meta or not isinstance(csrf_token := meta.get("content"), str):
82
+ msg = f"Failed to get the csrf token. ({res.status_code})"
83
+ raise ValueError(msg)
84
+ HEADERS.update({"x-csrf-token": csrf_token})
85
+ if not res.ok:
86
+ res = session.post(
87
+ f"{BASE_URL}/ai_life_update",
88
+ data={"ai_life": 3},
89
+ headers=HEADERS,
90
+ )
91
+ if not res.ok:
92
+ msg = f"Failed to update AI life. ({res.status_code})"
93
+ raise ValueError(msg)
94
+
95
+ result_sse = session.post(
96
+ f"{shindan_url}/ai_result",
97
+ json={
98
+ "form_values": user_inputs,
99
+ "shindan_token": params["_token"],
100
+ "ai_result_request_times": 0,
101
+ "encrypted_exec_key": params["encrypted_exec_key"],
102
+ },
103
+ headers=HEADERS,
104
+ )
105
+ gpt_results = "".join(
106
+ re.findall(r'"content":"([^"]+)', result_sse.text),
107
+ ).split("\n")
108
+ return {
109
+ "results": gpt_results,
110
+ "hashtags": [hashtag, "#shindanmaker"] if hashtag else ["#shindanmaker"],
111
+ "shindan_url": shindan_url,
112
+ }
113
+
114
+
115
+ def get_result_by_branch(
116
+ session: Session,
117
+ params: BranchParams,
118
+ *,
119
+ shindan_url: str,
120
+ ) -> ShindanResult:
121
+ """Get result by branch type shindan.
122
+
123
+ Args:
124
+ session (Session): session object
125
+ params (Params): input parameters fetched from shindan page
126
+ shindan_url (str): shindan url
127
+
128
+ Returns:
129
+ ShindanResult: the returned result from <https://shindanmaker.com>
130
+
131
+ """
132
+ return __get_result(session, params, is_renewal=True, shindan_url=shindan_url)
133
+
134
+
135
+ def get_result_by_check(
136
+ session: Session,
137
+ params: CheckParams,
138
+ *,
139
+ user_choices: dict[int, str],
140
+ shindan_url: str,
141
+ ) -> ShindanResult:
142
+ """Get result by check type shindan.
143
+
144
+ Args:
145
+ session (Session): session object
146
+ params (Params): input parameters fetched from shindan page
147
+ user_choices (dict[int, str]): choices inputted by user on terminal
148
+ shindan_url (str): shindan url
149
+
150
+ Returns:
151
+ ShindanResult: the returned result from <https://shindanmaker.com>
152
+
153
+ """
154
+ for choice_id, answer_id in user_choices.items():
155
+ params[f"input-check-choice[{choice_id}]"] = answer_id # type: ignore[literal-required]
156
+
157
+ return __get_result(session, params, is_renewal=True, shindan_url=shindan_url)
158
+
159
+
160
+ def get_result_by_name(
161
+ session: Session,
162
+ params: Params,
163
+ *,
164
+ shindan_url: str,
165
+ ) -> ShindanResult:
166
+ """Get result by name type shindan.
167
+
168
+ Args:
169
+ session (Session): session object
170
+ params (Params): input parameters fetched from shindan page
171
+ shindan_url (str): shindan url
172
+
173
+ Returns:
174
+ ShindanResult: the returned result from <https://shindanmaker.com>
175
+
176
+ """
177
+ return __get_result(session, params, shindan_url=shindan_url)
178
+
179
+
180
+ __all__ = (
181
+ "get_result_by_ai",
182
+ "get_result_by_branch",
183
+ "get_result_by_check",
184
+ "get_result_by_name",
185
+ )
@@ -0,0 +1,160 @@
1
+ """Interactive functions for the shindan CLI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ from shindan_cli.models import QuestionBranchChoice, QuestionChoiceChoice, UserInput, QuestionBranch, QuestionChoice
8
+
9
+ if TYPE_CHECKING:
10
+ from bs4 import BeautifulSoup
11
+
12
+ from .models import UserInputs
13
+
14
+
15
+ def get_user_inputs(
16
+ source: BeautifulSoup,
17
+ shindan_name: str,
18
+ ) -> UserInputs:
19
+ """Get user inputs from the shindan source.
20
+
21
+ Args:
22
+ source (BeautifulSoup): The source of the shindan page.
23
+ shindan_name (str): The name of the shindan.
24
+
25
+ Returns:
26
+ UserInputs: The user inputs.
27
+
28
+ """
29
+ user_inputs: dict[str, UserInput] = {}
30
+ form_labels = source.select("form#shindanForm > div.px-3 > div > span")
31
+ for idx, question in enumerate([*form_labels, *range(10 - len(form_labels))]):
32
+ if isinstance(question, int):
33
+ user_inputs[f"user_input_{idx + 1}"] = UserInput({"q": "", "a": None})
34
+ continue
35
+ question_text = question.text
36
+ if question_text == "あなたの名前":
37
+ user_inputs[f"user_input_{idx + 1}"] = UserInput({"q": question_text, "a": shindan_name})
38
+ continue
39
+ answer_text = None
40
+ while not answer_text:
41
+ answer_text = input(f"[{question_text}]: ").strip()
42
+ user_inputs[f"user_input_{idx + 1}"] = UserInput({"q": question_text, "a": answer_text})
43
+ return user_inputs
44
+
45
+
46
+ def get_rbr(source: BeautifulSoup) -> str:
47
+ """Get the result of the shindan from the source.
48
+
49
+ Args:
50
+ source (BeautifulSoup): The source of the shindan page.
51
+
52
+ Returns:
53
+ str: The result of the shindan.
54
+
55
+ """
56
+ question_branches: dict[str, QuestionBranch] = {}
57
+ for branch in source.select("div[id^='shindan_branch_'][data-kind='0']"):
58
+ branch_id = branch.get("id")
59
+ question = branch.select_one("p.shindan_branch_question")
60
+ if not isinstance(branch_id, str) or not question:
61
+ continue
62
+ question_branches[branch_id.replace("shindan_branch_", "")] = QuestionBranch(
63
+ {
64
+ "question": question.text.strip(),
65
+ "choices": [
66
+ QuestionBranchChoice(
67
+ {
68
+ "label": choice.text,
69
+ "next_branch_id": next_branch_id,
70
+ }
71
+ )
72
+ for choice in branch.select("button")
73
+ if isinstance(next_branch_id := choice.get("data-next_branch"), str)
74
+ ],
75
+ }
76
+ )
77
+
78
+ goal_branches: dict[str, str] = {}
79
+ for branch in source.select("div[id^='shindan_branch_'][data-kind='1']"):
80
+ branch_id = branch.get("id")
81
+ rbr = branch.get("data-rbr")
82
+ if not isinstance(branch_id, str) or not isinstance(rbr, str):
83
+ continue
84
+ goal_branches[branch_id.replace("shindan_branch_", "")] = rbr
85
+
86
+ current_branch_id = "1"
87
+ while current_branch_id not in goal_branches:
88
+ current_branch = question_branches[current_branch_id]
89
+ choices = current_branch["choices"]
90
+
91
+ print("[Q.", current_branch["question"], "]") # noqa: T201
92
+ for idx, choice in enumerate(choices):
93
+ print(f"> {idx}:", choice["label"]) # noqa: T201
94
+
95
+ inputted_text = input(">>> ").strip()
96
+ if not inputted_text:
97
+ continue
98
+ selected_id = int(inputted_text)
99
+ if 0 <= selected_id < len(choices):
100
+ current_branch_id = choices[selected_id]["next_branch_id"]
101
+
102
+ return goal_branches[current_branch_id]
103
+
104
+
105
+ def get_choices(source: BeautifulSoup) -> dict[int, str]:
106
+ """Get the choices from the shindan source.
107
+
108
+ Args:
109
+ source (BeautifulSoup): The source of the shindan page.
110
+
111
+ Returns:
112
+ dict[int, str]: The choices.
113
+
114
+ """
115
+ question_choices: dict[int, QuestionChoice] = {}
116
+ for question in source.select("div.check-username-target"):
117
+ order_id = question.get("data-order")
118
+ question_text = question.select_one("div > p > span")
119
+ if not isinstance(order_id, str) or not question_text:
120
+ continue
121
+ question_choices[int(order_id)] = QuestionChoice(
122
+ {
123
+ "question": question_text.text.strip(),
124
+ "choices": [
125
+ QuestionChoiceChoice({"label": choice.text.strip(), "choice_id": choice_key})
126
+ for choice in question.select("button.list-group-item")
127
+ if isinstance(choice_key := choice.get("data-choice_key"), str)
128
+ ],
129
+ }
130
+ )
131
+ current_question_id = 1
132
+ total_questions = len(question_choices)
133
+ answers: dict[int, str] = {}
134
+ while len(answers) < total_questions:
135
+ current_question = question_choices[current_question_id]
136
+ choices = current_question["choices"]
137
+ print( # noqa: T201
138
+ f"= {current_question_id}/{total_questions} =",
139
+ current_question["question"].strip(),
140
+ "===",
141
+ sep="\n",
142
+ )
143
+ for idx, choice in enumerate(choices):
144
+ print(f"> {idx}:", choice["label"]) # noqa: T201
145
+
146
+ inputted_text = input(">>> ").strip()
147
+ if not inputted_text:
148
+ continue
149
+ selected_id = int(inputted_text)
150
+ if 0 <= selected_id < len(choices):
151
+ answers[current_question_id] = choices[selected_id]["choice_id"]
152
+ current_question_id += 1
153
+ return answers
154
+
155
+
156
+ __all__ = (
157
+ "get_choices",
158
+ "get_rbr",
159
+ "get_user_inputs",
160
+ )
@@ -8,24 +8,45 @@ from pprint import pprint
8
8
  from . import __version__, shindan
9
9
 
10
10
 
11
- def _check_natural(v: str) -> int:
11
+ def __check_natural(v: str) -> int:
12
12
  if int(v) < 0:
13
- raise argparse.ArgumentTypeError("%s is an invalid natural int" % v)
13
+ msg = f"{v!r} is an invalid natural int"
14
+ raise argparse.ArgumentTypeError(msg)
14
15
  return int(v)
15
16
 
16
17
 
17
- def _parse_args(*, test: list[str] | None = None) -> argparse.Namespace:
18
+ def __parse_args(*, test: list[str] | None = None) -> argparse.Namespace:
18
19
  parser = argparse.ArgumentParser(
19
20
  prog="shindan",
20
21
  formatter_class=argparse.RawDescriptionHelpFormatter,
21
22
  description="ShindanMaker (https://shindanmaker.com) CLI",
22
23
  )
23
- parser.add_argument("page_id", metavar="ID", type=_check_natural, help="shindan page id")
24
+ parser.add_argument(
25
+ "page_id",
26
+ metavar="ID",
27
+ type=__check_natural,
28
+ help="shindan page id",
29
+ )
24
30
  parser.add_argument("shindan_name", metavar="NAME", type=str, help="shindan name")
25
31
  parser.add_argument("-w", "--wait", action="store_true", help="insert random wait")
26
- parser.add_argument("-H", "--hashtag", action="store_true", help="add hashtag `#shindanmaker`")
27
- parser.add_argument("-l", "--link", action="store_true", help="add link to last of output")
28
- parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {__version__}")
32
+ parser.add_argument(
33
+ "-H",
34
+ "--hashtag",
35
+ action="store_true",
36
+ help="add hashtag `#shindanmaker`",
37
+ )
38
+ parser.add_argument(
39
+ "-l",
40
+ "--link",
41
+ action="store_true",
42
+ help="add link to last of output",
43
+ )
44
+ parser.add_argument(
45
+ "-V",
46
+ "--version",
47
+ action="version",
48
+ version=f"%(prog)s {__version__}",
49
+ )
29
50
 
30
51
  # secret option!
31
52
  parser.add_argument("--debug", action="store_true", help=argparse.SUPPRESS)
@@ -36,8 +57,13 @@ def _parse_args(*, test: list[str] | None = None) -> argparse.Namespace:
36
57
 
37
58
 
38
59
  def main(*, test: list[str] | None = None) -> None:
39
- """Run CLI."""
40
- args = _parse_args(test=test)
60
+ """Run the shindan CLI.
61
+
62
+ Args:
63
+ test (list[str] | None, optional): test arguments. Defaults to None.
64
+
65
+ """
66
+ args = __parse_args(test=test)
41
67
  result = shindan(args.page_id, args.shindan_name, wait=args.wait)
42
68
 
43
69
  if args.debug:
@@ -0,0 +1,55 @@
1
+ """Models for shindan-cli."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TypedDict
6
+
7
+
8
+ class ShindanResult(TypedDict):
9
+ """TypedDict Class for result of shindan."""
10
+
11
+ results: list[str]
12
+ hashtags: list[str]
13
+ shindan_url: str
14
+
15
+
16
+ class QuestionBranchChoice(TypedDict):
17
+ label: str
18
+ next_branch_id: str
19
+
20
+
21
+ class QuestionBranch(TypedDict):
22
+ """TypedDict Class for question branch."""
23
+
24
+ question: str
25
+ choices: list[QuestionBranchChoice]
26
+
27
+
28
+ class QuestionChoiceChoice(TypedDict):
29
+ label: str
30
+ choice_id: str
31
+
32
+
33
+ class QuestionChoice(TypedDict):
34
+ """TypedDict Class for question choice."""
35
+
36
+ question: str
37
+ choices: list[QuestionChoiceChoice]
38
+
39
+
40
+ class UserInput(TypedDict):
41
+ """TypedDict Class for user input."""
42
+
43
+ q: str
44
+ a: str | None
45
+
46
+
47
+ UserInputs = dict[str, UserInput]
48
+
49
+ __all__ = (
50
+ "QuestionBranch",
51
+ "QuestionChoice",
52
+ "ShindanResult",
53
+ "UserInput",
54
+ "UserInputs",
55
+ )
@@ -0,0 +1,122 @@
1
+ """Implements the function to get the shindan result from <https://shindanmaker.com>."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import random
6
+ import time
7
+ from typing import cast
8
+
9
+ import cloudscraper # type: ignore[unused-ignore,import-not-found,import-untyped]
10
+ from bs4 import BeautifulSoup
11
+ from requests.sessions import Session
12
+
13
+ from .constants import BASE_URL, HEADERS, TARGET_KEYS_BY_TYPE
14
+ from .get_results import (
15
+ Params,
16
+ get_result_by_ai,
17
+ get_result_by_branch,
18
+ get_result_by_check,
19
+ get_result_by_name,
20
+ )
21
+ from .interactive import get_choices, get_rbr, get_user_inputs
22
+ from .models import ShindanResult
23
+
24
+
25
+ class ShindanError(Exception):
26
+ """Error class for shindan-cli."""
27
+
28
+
29
+ def shindan(
30
+ page_id: int,
31
+ shindan_name: str,
32
+ *,
33
+ wait: bool | None = False,
34
+ ) -> ShindanResult:
35
+ """Get the shindan result from <https://shindanmaker.com>.
36
+
37
+ Args:
38
+ page_id : int
39
+ shindan page id (e.g. `1036646`)
40
+ shindan_name : str
41
+ shindan name (e.g. your name)
42
+ wait : bool | None, optional
43
+ enable random waits while fetching shindan data, by default False
44
+
45
+ Returns:
46
+ ShindanResult: the returned result from <https://shindanmaker.com>
47
+
48
+ Raises:
49
+ ShindanError
50
+
51
+ """
52
+ if not isinstance(page_id, int) or page_id < 0:
53
+ msg = f"invalid page id: {page_id}"
54
+ raise ShindanError(msg)
55
+ shindan_url = f"{BASE_URL}/{page_id}"
56
+
57
+ session = cloudscraper.create_scraper()
58
+ assert isinstance(session, Session)
59
+
60
+ shindan_page = session.get(shindan_url, headers=HEADERS)
61
+ if shindan_page.status_code != 200:
62
+ raise ShindanError(shindan_page.status_code)
63
+
64
+ source = BeautifulSoup(shindan_page.text, features="lxml")
65
+
66
+ shindan_type_input = source.select_one('input[name="type"]')
67
+ if not shindan_type_input or not shindan_type_input.get("value"):
68
+ msg = "Cannot detect shindan type!"
69
+ raise ValueError(msg)
70
+ shindan_type = str(shindan_type_input.get("value"))
71
+ params = cast(
72
+ "Params",
73
+ {
74
+ key: key_input.get("value")
75
+ for key in TARGET_KEYS_BY_TYPE[shindan_type]
76
+ if (key_input := source.select_one(f'input[name="{key}"]'))
77
+ },
78
+ )
79
+ # overwrite randname (old: shindanName)
80
+ params["randname"] = shindan_name
81
+
82
+ if wait:
83
+ time.sleep(random.uniform(2, 5)) # noqa: S311
84
+
85
+ if params["type"] == "ai":
86
+ hashtag_title = source.select_one("h1#shindanTitle")
87
+ if not hashtag_title or not isinstance(
88
+ hashtag := hashtag_title.get("data-shindan_hashtag"),
89
+ str,
90
+ ):
91
+ hashtag = None
92
+ return get_result_by_ai(
93
+ session,
94
+ params,
95
+ user_inputs=get_user_inputs(source, shindan_name),
96
+ hashtag=hashtag,
97
+ shindan_url=shindan_url,
98
+ )
99
+ if params["type"] == "branch":
100
+ params["rbr"] = get_rbr(source)
101
+ return get_result_by_branch(
102
+ session,
103
+ params,
104
+ shindan_url=shindan_url,
105
+ )
106
+ if params["type"] == "check":
107
+ return get_result_by_check(
108
+ session,
109
+ params,
110
+ user_choices=get_choices(source),
111
+ shindan_url=shindan_url,
112
+ )
113
+ if params["type"] == "name":
114
+ return get_result_by_name(
115
+ session,
116
+ params,
117
+ shindan_url=shindan_url,
118
+ )
119
+ raise NotImplementedError(shindan_type)
120
+
121
+
122
+ __all__ = ("ShindanResult", "shindan")
@@ -1,87 +0,0 @@
1
- # poetry self add poetry-bumpversion
2
-
3
- [build-system]
4
- build-backend = "poetry.core.masonry.api"
5
- requires = [
6
- "poetry-core",
7
- ]
8
-
9
- [tool]
10
- [tool.black]
11
- line-length = 120
12
- target-version = ['py39']
13
-
14
- [tool.isort]
15
- profile = "black"
16
-
17
- [tool.mypy]
18
- pretty = true
19
- python_version = "3.9"
20
- show_error_codes = true
21
- strict = true
22
-
23
- [tool.ruff]
24
- ignore = [
25
- "D203", # 1 blank line required before class docstring
26
- "D213", # Multi-line docstring summary should start at the second line
27
- ]
28
- line-length = 120
29
- select = ["ALL"]
30
-
31
- [tool.ruff.mccabe]
32
- max-complexity = 18
33
-
34
- [tool.ruff.per-file-ignores]
35
- "tests/*.py" = [
36
- "D",
37
- "S101", # Use of assert detected
38
- ]
39
-
40
- [tool.poetry]
41
- authors = ["eggplants <w10776e8w@yahoo.co.jp>"]
42
- classifiers = [
43
- "Development Status :: 3 - Alpha",
44
- "License :: OSI Approved :: MIT License",
45
- "Programming Language :: Python :: 3",
46
- "Programming Language :: Python :: 3.7",
47
- "Programming Language :: Python :: 3.8",
48
- "Programming Language :: Python :: 3.9",
49
- "Programming Language :: Python :: 3.10",
50
- "Programming Language :: Python :: 3 :: Only",
51
- ]
52
- description = "ShindanMaker (https://shindanmaker.com) CLI"
53
- keywords = ["shindanmaker", "cli"]
54
- license = "MIT"
55
- name = "shindan_cli"
56
- packages = [{include = "shindan_cli"}]
57
- readme = "README.md"
58
- repository = "https://github.com/eggplants/shindan-cli"
59
- version = "1.3.0"
60
-
61
- [tool.poetry.dependencies]
62
- beautifulsoup4 = "^4.11.2"
63
- lxml = "^4.9.2"
64
- python = ">=3.7,<4"
65
- requests = "^2.28.2"
66
-
67
- [tool.poetry.group.dev.dependencies]
68
- lxml-stubs = "^0.4.0"
69
- mypy = ">=0.991,<1.4"
70
- pre-commit = "^2.20.0"
71
- pytest = "^7.2.2"
72
- pytest-cov = "^4.0.0"
73
- taskipy = "^1.10.3"
74
- types-beautifulsoup4 = "^4.11.6.7"
75
- types-requests = "^2.28.11.14"
76
-
77
- [tool.poetry.scripts]
78
- shindan = "shindan_cli.main:main"
79
-
80
- [tool.poetry_bumpversion.file."shindan_cli/__init__.py"]
81
-
82
- [tool.taskipy.tasks]
83
- lint = "pre-commit run -a"
84
- profile = "python -m cProfile"
85
- setup = "poetry install && pre-commit install -t pre-commit -t pre-push"
86
- test = "pytest --cov=shindan_cli --cov-report=term"
87
- "test:ci" = "task test --cov-report=xml:cov.xml"
@@ -1,7 +0,0 @@
1
- """Initialize shindan-cli package."""
2
- from __future__ import annotations
3
-
4
- from .shindan import ShindanError, ShindanResult, shindan
5
-
6
- __version__ = "1.3.0"
7
- __all__ = ("shindan", "ShindanResult", "ShindanError")
@@ -1,96 +0,0 @@
1
- """Implements the function to get the shindan result from <https://shindanmaker.com>."""
2
-
3
- from __future__ import annotations
4
-
5
- import random
6
- import time
7
- from typing import TypedDict
8
-
9
- import requests
10
- from bs4 import BeautifulSoup, Tag
11
-
12
-
13
- class ShindanResult(TypedDict):
14
- """TypedDict Class for result of shindan."""
15
-
16
- results: list[str]
17
- hashtags: list[str]
18
- shindan_url: str
19
-
20
-
21
- class ShindanError(Exception):
22
- """Error class for shindan-cli."""
23
-
24
-
25
- def shindan(page_id: int, shindan_name: str, *, wait: bool | None = False) -> ShindanResult:
26
- """Get the shindan result from <https://shindanmaker.com>.
27
-
28
- Parameters
29
- ----------
30
- page_id : int
31
- shindan page id (e.g. `1036646`)
32
- shindan_name : str
33
- shindan name (e.g. your name)
34
- wait : bool | None, optional
35
- enable random waits while fetching shindan data, by default False
36
-
37
- Returns
38
- -------
39
- ShindanResult
40
- the returned result from <https://shindanmaker.com>
41
-
42
- Raises
43
- ------
44
- ShindanError
45
- """
46
- headers = {
47
- "User-Agent": (
48
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
49
- "AppleWebKit/537.36 (KHTML, like Gecko) "
50
- "Chrome/96.0.4664.45 Safari/537.36"
51
- ),
52
- }
53
-
54
- if not isinstance(page_id, int) or page_id < 0:
55
- msg = f"invalid page id: {page_id}"
56
- raise ShindanError(msg)
57
-
58
- url = f"https://shindanmaker.com/{page_id}"
59
-
60
- session = requests.session()
61
- s = session.get(url, headers=headers)
62
- if s.status_code != requests.codes.ok:
63
- raise ShindanError(s.status_code)
64
-
65
- source = BeautifulSoup(s.text, features="lxml")
66
-
67
- # q, _token, shindanName, hiddenName, type, shindan_token, q
68
- params = {i["name"]: i["value"] for i in source.find_all("input")[1:5]}
69
-
70
- # overwrite shindanName
71
- params["shindanName"] = shindan_name
72
-
73
- login = session.post(url, data=params, headers=headers)
74
- if wait:
75
- time.sleep(random.uniform(2, 5)) # noqa: S311
76
-
77
- soup = BeautifulSoup(login.text, features="lxml")
78
- result_tag = soup.find(id="share-copytext-shindanresult-textarea")
79
-
80
- if not isinstance(result_tag, Tag) or not result_tag.text:
81
- msg = f"Could not find a tag contains the result, returns: {result_tag}"
82
- raise ShindanError(msg)
83
-
84
- *results, hashtag, shindan_url, _ = result_tag.text.split("\n")
85
-
86
- if not results[-1]:
87
- results.pop(-1)
88
-
89
- return {
90
- "results": results,
91
- "hashtags": hashtag.split("\xa0"),
92
- "shindan_url": shindan_url,
93
- }
94
-
95
-
96
- __all__ = ("ShindanResult", "shindan")
File without changes