threadkiller 3.0.2__tar.gz → 4.0.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.
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.editorconfig +6 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/inspectionProfiles/Project_Default.xml +3 -8
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/misc.xml +3 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/Containerfile +1 -1
- {threadkiller-3.0.2 → threadkiller-4.0.0}/PKG-INFO +4 -1
- {threadkiller-3.0.2 → threadkiller-4.0.0}/pyproject.toml +7 -1
- threadkiller-4.0.0/threadkiller/__init__.py +0 -0
- threadkiller-4.0.0/threadkiller/__main__.py +36 -0
- threadkiller-4.0.0/threadkiller/application.py +144 -0
- threadkiller-4.0.0/threadkiller/config.py +83 -0
- threadkiller-4.0.0/threadkiller/handlers.py +305 -0
- threadkiller-4.0.0/threadkiller/locale/__init__.py +51 -0
- threadkiller-4.0.0/threadkiller/locale/en/main.ftl +199 -0
- threadkiller-4.0.0/threadkiller/log.py +54 -0
- threadkiller-4.0.0/threadkiller/metadata.py +39 -0
- threadkiller-4.0.0/threadkiller/types.py +30 -0
- threadkiller-4.0.0/uv.lock +232 -0
- threadkiller-3.0.2/threadkiller/__main__.py +0 -55
- threadkiller-3.0.2/threadkiller/config.py +0 -22
- threadkiller-3.0.2/threadkiller/handlers.py +0 -63
- threadkiller-3.0.2/threadkiller/strings.py +0 -20
- threadkiller-3.0.2/uv.lock +0 -148
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.containerignore +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.forgejo/workflows/build-container-image-v.yaml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.forgejo/workflows/build-package.yaml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.forgejo/workflows/test-package.yaml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.gitignore +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/.gitignore +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/codeStyles/Project.xml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/codeStyles/codeStyleConfig.xml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/discord.xml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/icon.svg +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/jsonSchemas.xml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/modules.xml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/threadkiller.iml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.idea/vcs.xml +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.media/icon-512.png +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.media/icon.svg +0 -0
- /threadkiller-3.0.2/threadkiller/__init__.py → /threadkiller-4.0.0/.noai +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.vscode/extensions.json +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/.vscode/settings.json +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/LICENSE.txt +0 -0
- {threadkiller-3.0.2 → threadkiller-4.0.0}/compose.yml +0 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<inspection_tool class="LessResolvedByNameOnly" enabled="true" level="WARNING" enabled_by_default="true" />
|
|
7
7
|
<inspection_tool class="LessUnresolvedMixin" enabled="true" level="ERROR" enabled_by_default="true" />
|
|
8
8
|
<inspection_tool class="LessUnresolvedVariable" enabled="true" level="ERROR" enabled_by_default="true" />
|
|
9
|
-
<inspection_tool class="LongLine" enabled="
|
|
9
|
+
<inspection_tool class="LongLine" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
|
10
10
|
<inspection_tool class="PoetryPackageVersion" enabled="true" level="SERVER PROBLEM" enabled_by_default="true" />
|
|
11
11
|
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
|
12
12
|
<inspection_tool class="PyAbstractClassInspection" enabled="true" level="ERROR" enabled_by_default="true" />
|
|
@@ -26,17 +26,12 @@
|
|
|
26
26
|
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
|
27
27
|
<inspection_tool class="PyNestedDecoratorsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
|
28
28
|
<inspection_tool class="PyNoneFunctionAssignmentInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
|
29
|
-
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="ERROR" enabled_by_default="false"
|
|
30
|
-
<option name="ignoredPackages">
|
|
31
|
-
<value>
|
|
32
|
-
<list size="0" />
|
|
33
|
-
</value>
|
|
34
|
-
</option>
|
|
35
|
-
</inspection_tool>
|
|
29
|
+
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
36
30
|
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
|
37
31
|
<option name="ignoredErrors">
|
|
38
32
|
<list>
|
|
39
33
|
<option value="N806" />
|
|
34
|
+
<option value="N802" />
|
|
40
35
|
</list>
|
|
41
36
|
</option>
|
|
42
37
|
</inspection_tool>
|
|
@@ -6,4 +6,7 @@
|
|
|
6
6
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" project-jdk-name="Poetry (threadkiller)" project-jdk-type="Python SDK">
|
|
7
7
|
<output url="file://$PROJECT_DIR$/out" />
|
|
8
8
|
</component>
|
|
9
|
+
<component name="TaskProjectConfiguration">
|
|
10
|
+
<server type="Forgejo" url="https://g.starshard.space" />
|
|
11
|
+
</component>
|
|
9
12
|
</project>
|
|
@@ -23,7 +23,7 @@ CMD []
|
|
|
23
23
|
LABEL org.opencontainers.image.title="Threadkiller"
|
|
24
24
|
LABEL org.opencontainers.image.description="Telegram bot to delete messages sent outside of threads"
|
|
25
25
|
LABEL org.opencontainers.image.authors="Stefano Pigozzi <me@steffo.eu>"
|
|
26
|
-
LABEL org.opencontainers.image.version="
|
|
26
|
+
LABEL org.opencontainers.image.version="4.0.0"
|
|
27
27
|
LABEL org.opencontainers.image.licenses="EUPL-1.2"
|
|
28
28
|
LABEL org.opencontainers.image.url="https://g.starshard.space/steffo/-/packages/container/threadkiller/latest"
|
|
29
29
|
LABEL org.opencontainers.image.source="https://g.starshard.space/steffo/threadkiller"
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: threadkiller
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Telegram bot to delete messages sent outside of threads
|
|
5
5
|
Project-URL: Source, https://g.starshard.space/steffo/threadkiller
|
|
6
6
|
Project-URL: Issues, https://g.starshard.space/steffo/threadkiller/issues
|
|
7
7
|
Project-URL: Documentation, https://g.starshard.space/steffo/threadkiller/wiki/?action=_pages
|
|
8
|
+
Project-URL: Funding, https://liberapay.com/Steffo/
|
|
8
9
|
Project-URL: Telegram, https://t.me/the_threadkiller_bot?startgroup=yes
|
|
9
10
|
Author-email: Stefano Pigozzi <me@steffo.eu>
|
|
10
11
|
Maintainer-email: Stefano Pigozzi <me@steffo.eu>
|
|
@@ -22,4 +23,6 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
22
23
|
Classifier: Topic :: Communications :: Chat
|
|
23
24
|
Requires-Python: >=3.14
|
|
24
25
|
Requires-Dist: cfig[cli]>=0.3.10
|
|
26
|
+
Requires-Dist: coloredlogs>=15.0.1
|
|
27
|
+
Requires-Dist: fluent-runtime
|
|
25
28
|
Requires-Dist: python-telegram-bot>=22.8
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "threadkiller"
|
|
3
|
-
version = "
|
|
3
|
+
version = "4.0.0"
|
|
4
4
|
description = "Telegram bot to delete messages sent outside of threads"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Stefano Pigozzi", email = "me@steffo.eu" },
|
|
@@ -33,6 +33,8 @@ requires-python = ">=3.14"
|
|
|
33
33
|
dependencies = [
|
|
34
34
|
"python-telegram-bot>=22.8",
|
|
35
35
|
"cfig[cli]>=0.3.10",
|
|
36
|
+
"fluent-runtime", # From git
|
|
37
|
+
"coloredlogs>=15.0.1",
|
|
36
38
|
]
|
|
37
39
|
|
|
38
40
|
[project.scripts]
|
|
@@ -42,12 +44,16 @@ threadkiller = "threadkiller.__main__:main"
|
|
|
42
44
|
Source = "https://g.starshard.space/steffo/threadkiller"
|
|
43
45
|
Issues = "https://g.starshard.space/steffo/threadkiller/issues"
|
|
44
46
|
Documentation = "https://g.starshard.space/steffo/threadkiller/wiki/?action=_pages"
|
|
47
|
+
Funding = "https://liberapay.com/Steffo/"
|
|
45
48
|
Telegram = "https://t.me/the_threadkiller_bot?startgroup=yes"
|
|
46
49
|
|
|
47
50
|
[build-system]
|
|
48
51
|
requires = ["hatchling"]
|
|
49
52
|
build-backend = "hatchling.build"
|
|
50
53
|
|
|
54
|
+
[tool.uv.sources]
|
|
55
|
+
fluent-runtime = { git = "https://github.com/projectfluent/python-fluent", subdirectory = "fluent.runtime" }
|
|
56
|
+
|
|
51
57
|
[[tool.uv.index]]
|
|
52
58
|
name = "pypi"
|
|
53
59
|
url = "https://upload.pypi.org/simple/"
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from asyncio import new_event_loop, set_event_loop
|
|
2
|
+
from logging import getLogger
|
|
3
|
+
|
|
4
|
+
from threadkiller.application import make_application
|
|
5
|
+
from .config import config, TG_BOT_TOKEN
|
|
6
|
+
from .log import install_logging
|
|
7
|
+
from .metadata import set_commands
|
|
8
|
+
|
|
9
|
+
log = getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
log.debug("Verifying configuration")
|
|
14
|
+
config.proxies.resolve()
|
|
15
|
+
|
|
16
|
+
log.debug("Initializing logging")
|
|
17
|
+
install_logging()
|
|
18
|
+
|
|
19
|
+
log.info("Initializing")
|
|
20
|
+
|
|
21
|
+
log.debug("Creating event loop")
|
|
22
|
+
loop = new_event_loop()
|
|
23
|
+
set_event_loop(loop)
|
|
24
|
+
|
|
25
|
+
log.debug("Creating application")
|
|
26
|
+
application = make_application(token=TG_BOT_TOKEN.__wrapped__)
|
|
27
|
+
|
|
28
|
+
log.debug("Registering commands")
|
|
29
|
+
loop.run_until_complete(set_commands(bot=application.bot))
|
|
30
|
+
|
|
31
|
+
log.info("Initializing updater")
|
|
32
|
+
application.run_polling()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
main()
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from telegram.ext import ApplicationBuilder, MessageHandler, CommandHandler, Application, filters
|
|
4
|
+
|
|
5
|
+
from . import handlers
|
|
6
|
+
|
|
7
|
+
log = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def make_application(token: str) -> Application:
|
|
11
|
+
"""
|
|
12
|
+
Create the :class:`telegram.ext.Application` object powering the bot, and register all commands to it.
|
|
13
|
+
|
|
14
|
+
:param token: The bot token to use to authenticate to Telegram.
|
|
15
|
+
"""
|
|
16
|
+
log.debug("Creating application")
|
|
17
|
+
application: Application = ApplicationBuilder().token(token).build()
|
|
18
|
+
|
|
19
|
+
log.debug("Registering start command for private chats")
|
|
20
|
+
# noinspection bad-argument-type
|
|
21
|
+
application.add_handler(
|
|
22
|
+
CommandHandler(
|
|
23
|
+
callback=handlers.on_command_start_private,
|
|
24
|
+
command="start",
|
|
25
|
+
filters=filters.ChatType.PRIVATE,
|
|
26
|
+
block=False,
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
log.debug("Registering start command for group chats")
|
|
31
|
+
# noinspection bad-argument-type
|
|
32
|
+
application.add_handler(
|
|
33
|
+
CommandHandler(
|
|
34
|
+
callback=handlers.on_command_start_group,
|
|
35
|
+
command="start",
|
|
36
|
+
filters=filters.ChatType.GROUPS,
|
|
37
|
+
block=False,
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
log.debug("Registering addtogroup command")
|
|
42
|
+
# noinspection bad-argument-type
|
|
43
|
+
application.add_handler(
|
|
44
|
+
CommandHandler(
|
|
45
|
+
callback=handlers.on_command_addtogroup,
|
|
46
|
+
command="addtogroup",
|
|
47
|
+
filters=filters.ChatType.PRIVATE,
|
|
48
|
+
block=False,
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
log.debug("Registering help command")
|
|
53
|
+
# noinspection bad-argument-type
|
|
54
|
+
application.add_handler(
|
|
55
|
+
CommandHandler(
|
|
56
|
+
callback=handlers.on_command_help,
|
|
57
|
+
command="help",
|
|
58
|
+
filters=filters.ChatType.PRIVATE,
|
|
59
|
+
block=False,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
log.debug("Registering settings command")
|
|
64
|
+
# noinspection bad-argument-type
|
|
65
|
+
application.add_handler(
|
|
66
|
+
CommandHandler(
|
|
67
|
+
callback=handlers.on_command_settings,
|
|
68
|
+
command="settings",
|
|
69
|
+
filters=filters.ChatType.PRIVATE,
|
|
70
|
+
block=False,
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
log.debug("Registering settings command")
|
|
75
|
+
# noinspection bad-argument-type
|
|
76
|
+
application.add_handler(
|
|
77
|
+
CommandHandler(
|
|
78
|
+
callback=handlers.on_command_settings,
|
|
79
|
+
command="settings",
|
|
80
|
+
filters=filters.ChatType.PRIVATE,
|
|
81
|
+
block=False,
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
log.debug("Registering support command")
|
|
86
|
+
# noinspection bad-argument-type
|
|
87
|
+
application.add_handler(
|
|
88
|
+
CommandHandler(
|
|
89
|
+
callback=handlers.on_command_support,
|
|
90
|
+
command="support",
|
|
91
|
+
filters=filters.ChatType.PRIVATE,
|
|
92
|
+
block=False,
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
log.debug("Registering version command")
|
|
97
|
+
# noinspection bad-argument-type
|
|
98
|
+
application.add_handler(
|
|
99
|
+
CommandHandler(
|
|
100
|
+
callback=handlers.on_command_version,
|
|
101
|
+
command="version",
|
|
102
|
+
filters=filters.ChatType.PRIVATE,
|
|
103
|
+
block=False,
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
log.debug("Registering privacy command")
|
|
108
|
+
# noinspection bad-argument-type
|
|
109
|
+
application.add_handler(
|
|
110
|
+
CommandHandler(
|
|
111
|
+
callback=handlers.on_command_privacy,
|
|
112
|
+
command="privacy",
|
|
113
|
+
filters=filters.ChatType.PRIVATE,
|
|
114
|
+
block=False,
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
log.debug("Registering donate command")
|
|
119
|
+
# noinspection bad-argument-type
|
|
120
|
+
application.add_handler(
|
|
121
|
+
CommandHandler(
|
|
122
|
+
callback=handlers.on_command_donate,
|
|
123
|
+
command="donate",
|
|
124
|
+
filters=filters.ChatType.PRIVATE,
|
|
125
|
+
block=False,
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
log.debug("Registering group message handler")
|
|
130
|
+
# noinspection bad-argument-type
|
|
131
|
+
application.add_handler(
|
|
132
|
+
MessageHandler(
|
|
133
|
+
callback=handlers.on_message_group,
|
|
134
|
+
filters=~filters.REPLY & filters.ChatType.GROUPS & ~filters.User(user_id=777000) & ~filters.StatusUpdate.ALL & ~filters.COMMAND,
|
|
135
|
+
block=False,
|
|
136
|
+
)
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return application
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
__all__ = (
|
|
143
|
+
"make_application",
|
|
144
|
+
)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import cfig
|
|
2
|
+
|
|
3
|
+
config = cfig.Configuration()
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@config.required()
|
|
7
|
+
def TG_BOT_TOKEN(val: str) -> str:
|
|
8
|
+
"""
|
|
9
|
+
Token used to authenticate as a Telegram bot.
|
|
10
|
+
|
|
11
|
+
Obtain one at https://t.me/BotFather .
|
|
12
|
+
"""
|
|
13
|
+
return val
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@config.optional()
|
|
17
|
+
def SUPPORT_GROUP_LINK(val: str | None) -> str | None:
|
|
18
|
+
"""
|
|
19
|
+
Invite link to the bot's support group.
|
|
20
|
+
|
|
21
|
+
Displayed in /support.
|
|
22
|
+
"""
|
|
23
|
+
return val
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@config.optional()
|
|
27
|
+
def SUPPORT_EMAIL_RAW(val: str | None) -> str | None:
|
|
28
|
+
"""
|
|
29
|
+
Email of the bot's owner, without `mailto:` prefix.
|
|
30
|
+
|
|
31
|
+
Displayed in /support.
|
|
32
|
+
"""
|
|
33
|
+
return val
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@config.optional()
|
|
37
|
+
def SUPPORT_OWNER_LINK(val: str | None) -> str | None:
|
|
38
|
+
"""
|
|
39
|
+
t.me link of the bot's owner.
|
|
40
|
+
|
|
41
|
+
Displayed in /support.
|
|
42
|
+
"""
|
|
43
|
+
return val
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@config.optional()
|
|
47
|
+
def LINK_SOURCE(val: str | None) -> str:
|
|
48
|
+
"""
|
|
49
|
+
Link to the bot's source code.
|
|
50
|
+
|
|
51
|
+
Displayed in /version.
|
|
52
|
+
"""
|
|
53
|
+
if val is None:
|
|
54
|
+
return "https://g.starshard.space/steffo/threadkiller"
|
|
55
|
+
else:
|
|
56
|
+
return val
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@config.optional()
|
|
60
|
+
def LINK_DONATE(val: str | None) -> str:
|
|
61
|
+
"""
|
|
62
|
+
Link to the bot's source code.
|
|
63
|
+
|
|
64
|
+
Displayed in /version.
|
|
65
|
+
"""
|
|
66
|
+
if val is None:
|
|
67
|
+
return "https://liberapay.com/Steffo/"
|
|
68
|
+
else:
|
|
69
|
+
return val
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = (
|
|
73
|
+
"config",
|
|
74
|
+
"TG_BOT_TOKEN",
|
|
75
|
+
"SUPPORT_GROUP_LINK",
|
|
76
|
+
"SUPPORT_EMAIL_RAW",
|
|
77
|
+
"SUPPORT_OWNER_LINK",
|
|
78
|
+
"LINK_SOURCE",
|
|
79
|
+
"LINK_DONATE",
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__":
|
|
83
|
+
config.cli()
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
from importlib.metadata import version
|
|
2
|
+
from logging import getLogger
|
|
3
|
+
|
|
4
|
+
from fluent.runtime import FluentLocalization
|
|
5
|
+
from telegram import Update, Chat, User, Message, error
|
|
6
|
+
from telegram.constants import ParseMode
|
|
7
|
+
from telegram.ext import CallbackContext
|
|
8
|
+
|
|
9
|
+
from .config import SUPPORT_EMAIL_RAW, SUPPORT_GROUP_LINK, SUPPORT_OWNER_LINK, LINK_DONATE, LINK_SOURCE
|
|
10
|
+
from .locale import localize
|
|
11
|
+
|
|
12
|
+
log = getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@localize
|
|
16
|
+
async def on_command_start_private(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Handler for the /start command.
|
|
19
|
+
"""
|
|
20
|
+
log.debug("Handling /start in private chat")
|
|
21
|
+
|
|
22
|
+
# This invariant is covered by the application, before the handler is called
|
|
23
|
+
chat = update.effective_chat
|
|
24
|
+
assert isinstance(chat, Chat)
|
|
25
|
+
|
|
26
|
+
await chat.send_message(
|
|
27
|
+
text=locale.format_value("command-start-private-success", {
|
|
28
|
+
"bot-name": context.bot.username,
|
|
29
|
+
}),
|
|
30
|
+
parse_mode=ParseMode.HTML,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@localize
|
|
35
|
+
async def on_command_start_group(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Handler for the /start command.
|
|
38
|
+
"""
|
|
39
|
+
log.debug("Handling /start in group")
|
|
40
|
+
|
|
41
|
+
# These invariants are covered by the application, before the handler is called
|
|
42
|
+
chat = update.effective_chat
|
|
43
|
+
message = update.effective_message
|
|
44
|
+
sender = update.effective_sender
|
|
45
|
+
assert isinstance(chat, Chat)
|
|
46
|
+
assert isinstance(message, Message)
|
|
47
|
+
assert isinstance(sender, User)
|
|
48
|
+
|
|
49
|
+
await chat.send_message(
|
|
50
|
+
text=locale.format_value("command-start-group-success", {
|
|
51
|
+
"bot-name": context.bot.username,
|
|
52
|
+
"url-donate": LINK_DONATE.__wrapped__,
|
|
53
|
+
}),
|
|
54
|
+
parse_mode=ParseMode.HTML,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@localize
|
|
59
|
+
async def on_command_addtogroup(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
60
|
+
"""
|
|
61
|
+
Handler for the /addtogroup command.
|
|
62
|
+
"""
|
|
63
|
+
log.debug("Handling /addtogroup")
|
|
64
|
+
|
|
65
|
+
# These invariants are covered by the application, before the handler is called
|
|
66
|
+
chat = update.effective_chat
|
|
67
|
+
message = update.effective_message
|
|
68
|
+
sender = update.effective_sender
|
|
69
|
+
assert isinstance(chat, Chat)
|
|
70
|
+
assert isinstance(message, Message)
|
|
71
|
+
assert isinstance(sender, User)
|
|
72
|
+
|
|
73
|
+
await chat.send_message(
|
|
74
|
+
text=locale.format_value("command-addtogroup-success", {
|
|
75
|
+
"bot-name": context.bot.username,
|
|
76
|
+
"url-notify": f"https://t.me/{context.bot.username}?startgroup=yes&admin=anonymous",
|
|
77
|
+
"url-delete": f"https://t.me/{context.bot.username}?startgroup=yes&admin=anonymous+delete_messages",
|
|
78
|
+
}),
|
|
79
|
+
parse_mode=ParseMode.HTML,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@localize
|
|
84
|
+
async def on_command_help(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
85
|
+
"""
|
|
86
|
+
Handler for the /help command.
|
|
87
|
+
"""
|
|
88
|
+
log.debug("Handling /help")
|
|
89
|
+
|
|
90
|
+
# These invariants are covered by the application, before the handler is called
|
|
91
|
+
chat = update.effective_chat
|
|
92
|
+
message = update.effective_message
|
|
93
|
+
sender = update.effective_sender
|
|
94
|
+
assert isinstance(chat, Chat)
|
|
95
|
+
assert isinstance(message, Message)
|
|
96
|
+
assert isinstance(sender, User)
|
|
97
|
+
|
|
98
|
+
await chat.send_message(
|
|
99
|
+
text=locale.format_value("command-help-success", {
|
|
100
|
+
"bot-name": context.bot.username,
|
|
101
|
+
}),
|
|
102
|
+
parse_mode=ParseMode.HTML,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@localize
|
|
107
|
+
async def on_command_settings(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Handler for the /settings command.
|
|
110
|
+
"""
|
|
111
|
+
log.debug("Handling /settings")
|
|
112
|
+
|
|
113
|
+
# These invariants are covered by the application, before the handler is called
|
|
114
|
+
chat = update.effective_chat
|
|
115
|
+
message = update.effective_message
|
|
116
|
+
sender = update.effective_sender
|
|
117
|
+
assert isinstance(chat, Chat)
|
|
118
|
+
assert isinstance(message, Message)
|
|
119
|
+
assert isinstance(sender, User)
|
|
120
|
+
|
|
121
|
+
await chat.send_message(
|
|
122
|
+
text=locale.format_value("command-settings-success", {
|
|
123
|
+
"bot-name": context.bot.username,
|
|
124
|
+
}),
|
|
125
|
+
parse_mode=ParseMode.HTML,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@localize
|
|
130
|
+
async def on_command_support(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
131
|
+
"""
|
|
132
|
+
Handler for the /support command.
|
|
133
|
+
"""
|
|
134
|
+
log.debug("Handling /support")
|
|
135
|
+
|
|
136
|
+
# These invariants are covered by the application, before the handler is called
|
|
137
|
+
chat = update.effective_chat
|
|
138
|
+
message = update.effective_message
|
|
139
|
+
sender = update.effective_sender
|
|
140
|
+
assert isinstance(chat, Chat)
|
|
141
|
+
assert isinstance(message, Message)
|
|
142
|
+
assert isinstance(sender, User)
|
|
143
|
+
|
|
144
|
+
fluent_message = locale.format_message("command-support-success", {
|
|
145
|
+
"bot-name": context.bot.username,
|
|
146
|
+
"bot-group": SUPPORT_GROUP_LINK.__wrapped__ if SUPPORT_GROUP_LINK is not None else None,
|
|
147
|
+
"bot-email": SUPPORT_EMAIL_RAW.__wrapped__ if SUPPORT_EMAIL_RAW is not None else None,
|
|
148
|
+
"bot-owner": SUPPORT_OWNER_LINK.__wrapped__ if SUPPORT_OWNER_LINK is not None else None,
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
text = fluent_message.value
|
|
152
|
+
assert text is not None
|
|
153
|
+
|
|
154
|
+
if SUPPORT_GROUP_LINK:
|
|
155
|
+
text += "\n"
|
|
156
|
+
text += fluent_message.attributes["group"]
|
|
157
|
+
|
|
158
|
+
if SUPPORT_EMAIL_RAW:
|
|
159
|
+
text += "\n"
|
|
160
|
+
text += fluent_message.attributes["email"]
|
|
161
|
+
|
|
162
|
+
if SUPPORT_OWNER_LINK:
|
|
163
|
+
text += "\n"
|
|
164
|
+
text += fluent_message.attributes["owner"]
|
|
165
|
+
|
|
166
|
+
if not (SUPPORT_GROUP_LINK or SUPPORT_EMAIL_RAW or SUPPORT_OWNER_LINK):
|
|
167
|
+
text += "\n"
|
|
168
|
+
text += fluent_message.attributes["none"]
|
|
169
|
+
|
|
170
|
+
await chat.send_message(
|
|
171
|
+
text=text,
|
|
172
|
+
parse_mode=ParseMode.HTML,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@localize
|
|
177
|
+
async def on_command_version(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
178
|
+
"""
|
|
179
|
+
Handler for the /version command.
|
|
180
|
+
"""
|
|
181
|
+
log.debug("Handling /version")
|
|
182
|
+
|
|
183
|
+
# These invariants are covered by the application, before the handler is called
|
|
184
|
+
chat = update.effective_chat
|
|
185
|
+
message = update.effective_message
|
|
186
|
+
sender = update.effective_sender
|
|
187
|
+
assert isinstance(chat, Chat)
|
|
188
|
+
assert isinstance(message, Message)
|
|
189
|
+
assert isinstance(sender, User)
|
|
190
|
+
|
|
191
|
+
bot_software = "threadkiller"
|
|
192
|
+
bot_version = version(bot_software)
|
|
193
|
+
|
|
194
|
+
await chat.send_message(
|
|
195
|
+
text=locale.format_value("command-version-success", {
|
|
196
|
+
"bot-name": context.bot.username,
|
|
197
|
+
"bot-software": bot_software,
|
|
198
|
+
"bot-version": bot_version,
|
|
199
|
+
"url-source": LINK_SOURCE.__wrapped__,
|
|
200
|
+
}),
|
|
201
|
+
parse_mode=ParseMode.HTML,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@localize
|
|
206
|
+
async def on_command_privacy(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
207
|
+
"""
|
|
208
|
+
Handler for the /privacy command.
|
|
209
|
+
"""
|
|
210
|
+
log.debug("Handling /privacy")
|
|
211
|
+
|
|
212
|
+
# These invariants are covered by the application, before the handler is called
|
|
213
|
+
chat = update.effective_chat
|
|
214
|
+
message = update.effective_message
|
|
215
|
+
sender = update.effective_sender
|
|
216
|
+
assert isinstance(chat, Chat)
|
|
217
|
+
assert isinstance(message, Message)
|
|
218
|
+
assert isinstance(sender, User)
|
|
219
|
+
|
|
220
|
+
await chat.send_message(
|
|
221
|
+
text=locale.format_value("command-privacy-success", {
|
|
222
|
+
"bot-name": context.bot.username,
|
|
223
|
+
"url-telegram-api": "https://core.telegram.org/bots",
|
|
224
|
+
}),
|
|
225
|
+
parse_mode=ParseMode.HTML,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@localize
|
|
230
|
+
async def on_command_donate(update: Update, context: CallbackContext, *, locale: FluentLocalization) -> None:
|
|
231
|
+
"""
|
|
232
|
+
Handler for the /donate command.
|
|
233
|
+
"""
|
|
234
|
+
log.debug("Handling /donate")
|
|
235
|
+
|
|
236
|
+
# These invariants are covered by the application, before the handler is called
|
|
237
|
+
chat = update.effective_chat
|
|
238
|
+
message = update.effective_message
|
|
239
|
+
sender = update.effective_sender
|
|
240
|
+
assert isinstance(chat, Chat)
|
|
241
|
+
assert isinstance(message, Message)
|
|
242
|
+
assert isinstance(sender, User)
|
|
243
|
+
|
|
244
|
+
await chat.send_message(
|
|
245
|
+
text=locale.format_value("command-donate-success", {
|
|
246
|
+
"bot-name": context.bot.username,
|
|
247
|
+
"url-donate": LINK_DONATE.__wrapped__,
|
|
248
|
+
}),
|
|
249
|
+
parse_mode=ParseMode.HTML,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@localize
|
|
254
|
+
async def on_message_group(update: Update, context: CallbackContext, locale: FluentLocalization) -> None:
|
|
255
|
+
"""
|
|
256
|
+
Handler for any message received in a group.
|
|
257
|
+
"""
|
|
258
|
+
log.debug("Handling group message")
|
|
259
|
+
|
|
260
|
+
# These invariants are covered by the application, before the handler is called
|
|
261
|
+
chat = update.effective_chat
|
|
262
|
+
message = update.effective_message
|
|
263
|
+
sender = update.effective_sender
|
|
264
|
+
assert isinstance(chat, Chat)
|
|
265
|
+
assert isinstance(message, Message)
|
|
266
|
+
assert isinstance(sender, User)
|
|
267
|
+
|
|
268
|
+
await message.copy(
|
|
269
|
+
chat_id=chat.id,
|
|
270
|
+
api_kwargs=dict(
|
|
271
|
+
ephemeral_message_parameters=dict(
|
|
272
|
+
receiver_user_id=sender.id,
|
|
273
|
+
)
|
|
274
|
+
),
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
try:
|
|
278
|
+
await message.delete()
|
|
279
|
+
except (error.Forbidden, error.BadRequest):
|
|
280
|
+
text = locale.format_value("message-notified")
|
|
281
|
+
else:
|
|
282
|
+
text = locale.format_value("message-deleted")
|
|
283
|
+
|
|
284
|
+
await chat.send_message(
|
|
285
|
+
text=text,
|
|
286
|
+
parse_mode=ParseMode.HTML,
|
|
287
|
+
api_kwargs=dict(
|
|
288
|
+
ephemeral_message_parameters=dict(
|
|
289
|
+
receiver_user_id=sender.id,
|
|
290
|
+
)
|
|
291
|
+
),
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
__all__ = (
|
|
296
|
+
"on_command_start_private",
|
|
297
|
+
"on_command_addtogroup",
|
|
298
|
+
"on_command_help",
|
|
299
|
+
"on_command_settings",
|
|
300
|
+
"on_command_support",
|
|
301
|
+
"on_command_version",
|
|
302
|
+
"on_command_privacy",
|
|
303
|
+
"on_command_donate",
|
|
304
|
+
"on_message_group",
|
|
305
|
+
)
|