From 6315c4dd534308ac3b2f132d5ac0e2afdb5b871a Mon Sep 17 00:00:00 2001
From: BingLingGroup <42505588+BingLingGroup@users.noreply.github.com>
Date: Wed, 11 Mar 2020 16:57:37 +0800
Subject: [PATCH 1/4] Fix ubuntu install command in readme
---
README.md | 2 +-
docs/README.zh-Hans.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index c32e92e..be287a6 100644
--- a/README.md
+++ b/README.md
@@ -82,7 +82,7 @@ Include dependencies installation commands.
Install from `master` branch.
```bash
-apt install python3 python-pip3 git -y
+apt install python3 python3-pip git -y
pip3 install git+https://github.com/BingLingGroup/delethon.git@master
```
diff --git a/docs/README.zh-Hans.md b/docs/README.zh-Hans.md
index cb1e9c3..f9a007f 100644
--- a/docs/README.zh-Hans.md
+++ b/docs/README.zh-Hans.md
@@ -82,7 +82,7 @@ pip install .
从`master`分支安装。
```bash
-apt install python3 python-pip3 git -y
+apt install python3 python3-pip git -y
pip3 install git+https://github.com/BingLingGroup/delethon.git@master
```
From bdb6833cb2493b3b7e15d1c7f8c704077ca58b87 Mon Sep 17 00:00:00 2001
From: BingLingGroup <42505588+BingLingGroup@users.noreply.github.com>
Date: Wed, 11 Mar 2020 21:23:09 +0800
Subject: [PATCH 2/4] Fix print bugs Update readme
---
CHANGELOG.md | 6 +++++-
README.md | 18 +++++++++++++++++-
delethon/__init__.py | 28 +++++++++++++++++-----------
docs/CHANGELOG.zh-Hans.md | 31 +++++++++++++++++--------------
docs/README.zh-Hans.md | 18 +++++++++++++++++-
5 files changed, 73 insertions(+), 28 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a50b91..99d2f43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,12 +13,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Added](#addedunreleased)
- [Changed](#changedunreleased)
- [0.1.0-alpha - 2020-03-11](#010-alpha---2020-03-11)
- - [Added](#added040-alpha)
+ - [Added](#added010-alpha)
Click up arrow to go back to TOC.
### [Unreleased]
+#### Changed(Unreleased)
+
+- Fix print bugs.
+
### [0.1.0-alpha] - 2020-03-11
#### Added(0.1.0-alpha)
diff --git a/README.md b/README.md
index be287a6..1630ce8 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ It can do:
It can not do:
-- [ ] Delete the messages that's been cached or exported to the local storage.
+- [ ] Delete the messages that's been cached, [anti-revoked](https://github.com/SpriteOvO/Telegram-Anti-Revoke) or exported to the local storage.
- [ ] Delete the messages in group's recent actions.
- [ ] Delete other people's messages for all in group chats unless you have the admin rights of the group.
@@ -79,6 +79,13 @@ pip install .
Include dependencies installation commands.
+Install from `dev` branch.
+
+```bash
+apt install python3 python3-pip git -y
+pip3 install git+https://github.com/BingLingGroup/delethon.git@dev
+```
+
Install from `master` branch.
```bash
@@ -102,6 +109,15 @@ Choco installation command is for cmd.(not Powershell)
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
```
+Install from `dev` branch.
+
+```batch
+choco install git python curl -y
+curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
+python get-pip.py
+pip install git+https://github.com/BingLingGroup/delethon.git@dev
+```
+
Install from `master` branch.
```batch
diff --git a/delethon/__init__.py b/delethon/__init__.py
index e9964ff..125a20c 100644
--- a/delethon/__init__.py
+++ b/delethon/__init__.py
@@ -46,6 +46,8 @@ async def iter_users_msg( # pylint: disable=too-many-arguments, too-many-branch
"""
msg_count = 0
id_user_dict = {}
+ if args.log_level > 0:
+ print()
if not user:
async for message in client.iter_messages(
chat_entity,
@@ -200,7 +202,7 @@ async def iter_dialog( # pylint: disable=too-many-branches, too-many-statements
if not args.chats:
if args.log_level > 0:
print("Error: No chats input.")
- return 1
+ return
for chat in args.chats:
try:
chat_entity = await client.get_input_entity(chat)
@@ -224,14 +226,6 @@ async def iter_dialog( # pylint: disable=too-many-branches, too-many-statements
msg_filter=msg_filter,
media_filters=media_filters)
- if not args.only_print:
- if args.log_level > 0:
- print(_("Delete {msg_count} messages in total.").format(
- msg_count=total))
- else:
- print(_("Print {msg_count} messages in total.").format(
- msg_count=total))
-
else:
if args.users:
for user in args.users:
@@ -249,6 +243,10 @@ async def iter_dialog( # pylint: disable=too-many-branches, too-many-statements
msg_filter=msg_filter,
media_filters=media_filters)
else:
+ if not args.chats:
+ if args.log_level > 0:
+ print("Error: No chats input.")
+ return
for chat in args.chats:
try:
chat_entity = await client.get_input_entity(chat)
@@ -274,6 +272,14 @@ async def iter_dialog( # pylint: disable=too-many-branches, too-many-statements
msg_filter=msg_filter,
media_filters=media_filters)
+ if not args.only_print:
+ if args.log_level > 0:
+ print(_("Delete {msg_count} messages in total.").format(
+ msg_count=total))
+ else:
+ print(_("Print {msg_count} messages in total.").format(
+ msg_count=total))
+
def str_to_msg_filter(filter_str): # pylint: disable=too-many-branches
"""
@@ -388,12 +394,12 @@ def main(): # pylint: disable=too-many-branches
if not args.api_id:
if args.log_level > 0:
print("Error: No api_id input.")
- return 1
+ return 1
if not args.api_hash:
if args.log_level > 0:
print("Error: No api_hash input.")
- return 1
+ return 1
if args.log_level == 0 and args.only_print:
return 1
diff --git a/docs/CHANGELOG.zh-Hans.md b/docs/CHANGELOG.zh-Hans.md
index 7a50b91..25b1cfb 100644
--- a/docs/CHANGELOG.zh-Hans.md
+++ b/docs/CHANGELOG.zh-Hans.md
@@ -1,29 +1,32 @@
-## Changelog
+## 更新日志
-[简体中文](docs/CHANGELOG.zh-Hans.md)
+[English](../CHANGELOG.md)
-All notable changes to this project will be documented in this file.
+本项目的所有明显改变将被记录在这个文件里。
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
-and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+本文件的格式将会基于[Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),同时本项目的版本号将遵守[Semantic Versioning](https://semver.org/lang/zh-CN/)。
-## TOC
+## 目录
-- [Unreleased](#unreleased)
- - [Added](#addedunreleased)
- - [Changed](#changedunreleased)
+- [未发布](#未发布)
+ - [添加](#添加未发布)
+ - [修改](#修改未发布)
- [0.1.0-alpha - 2020-03-11](#010-alpha---2020-03-11)
- - [Added](#added040-alpha)
+ - [添加](#添加010-alpha)
-Click up arrow to go back to TOC.
+点击上箭头以返回目录。
-### [Unreleased]
+### [未发布]
+
+#### 修改(未发布)
+
+- 修复输出问题。
### [0.1.0-alpha] - 2020-03-11
-#### Added(0.1.0-alpha)
+#### 添加(0.1.0-alpha)
-- Add basic messages deleting functions.
+- 添加基本消息删除功能。
↑
diff --git a/docs/README.zh-Hans.md b/docs/README.zh-Hans.md
index f9a007f..f19ac72 100644
--- a/docs/README.zh-Hans.md
+++ b/docs/README.zh-Hans.md
@@ -40,7 +40,7 @@
它不能做到:
-- [ ] 删除已被缓存或者导出到本地的消息。
+- [ ] 删除已被缓存,已被[防撤回](https://github.com/SpriteOvO/Telegram-Anti-Revoke)或者导出到本地的消息。
- [ ] 删除群组最近活动中的消息。
- [ ] 删除群组中其他人的消息,除非你有群组管理员权限。
@@ -79,6 +79,13 @@ pip install .
包括依赖安装指令。
+从`dev`分支安装。
+
+```bash
+apt install python3 python3-pip git -y
+pip3 install git+https://github.com/BingLingGroup/delethon.git@dev
+```
+
从`master`分支安装。
```bash
@@ -102,6 +109,15 @@ pip3 install git+https://github.com/BingLingGroup/delethon.git@master
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
```
+从`dev`分支安装。
+
+```batch
+choco install git python curl -y
+curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
+python get-pip.py
+pip install git+https://github.com/BingLingGroup/delethon.git@dev
+```
+
从`master`分支安装。
```batch
From 73e80743373c58111cdcbc5417874c3f2fa71b9d Mon Sep 17 00:00:00 2001
From: BingLingGroup <42505588+BingLingGroup@users.noreply.github.com>
Date: Wed, 18 Mar 2020 09:58:48 +0800
Subject: [PATCH 3/4] Add exceptions for __init__.py
---
delethon/__init__.py | 189 +++++++++++++++++++++--------------------
delethon/exceptions.py | 25 ++++++
2 files changed, 122 insertions(+), 92 deletions(-)
create mode 100644 delethon/exceptions.py
diff --git a/delethon/__init__.py b/delethon/__init__.py
index 125a20c..e256974 100644
--- a/delethon/__init__.py
+++ b/delethon/__init__.py
@@ -18,6 +18,7 @@
# Any changes to the path and your own modules
from delethon import options
from delethon import constants
+from delethon import exceptions
INIT_TEXT = gettext.translation(domain=__name__,
@@ -391,102 +392,106 @@ def main(): # pylint: disable=too-many-branches
"""
args = options.get_cmd_args()
- if not args.api_id:
- if args.log_level > 0:
- print("Error: No api_id input.")
- return 1
+ try:
+ if not args.api_id:
+ raise exceptions.DelethonException(_("Error: No api_id input."))
+
+ if not args.api_hash:
+ raise exceptions.DelethonException(_("Error: No api_hash input."))
+
+ if args.log_level == 0 and args.only_print:
+ raise exceptions.DelethonException("")
+
+ if args.proxy_type == "SOCKS5":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.SOCKS5,
+ args.proxy_address,
+ args.proxy_port,
+ args.proxy_username,
+ args.proxy_password))
+ elif args.proxy_type == "SOCKS4":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.SOCKS4,
+ args.proxy_address,
+ args.proxy_port,
+ args.proxy_username,
+ args.proxy_password))
+ elif args.proxy_type == "HTTP":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.HTTP,
+ args.proxy_address,
+ args.proxy_port,
+ args.proxy_username,
+ args.proxy_password))
+ elif args.proxy_type == "MTPROTO":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ connection=
+ telethon.connection.ConnectionTcpMTProxyRandomizedIntermediate,
+ proxy=(args.proxy_address,
+ args.proxy_port,
+ args.proxy_password))
+ elif os.environ.get("HTTP_PROXY"):
+ http_proxy_list = os.environ["HTTP_PROXY"].split(":")
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.HTTP,
+ http_proxy_list[1][2:],
+ int(http_proxy_list[2]),
+ args.proxy_username,
+ args.proxy_password))
+ else:
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash)
- if not args.api_hash:
- if args.log_level > 0:
- print("Error: No api_hash input.")
- return 1
-
- if args.log_level == 0 and args.only_print:
- return 1
-
- if args.proxy_type == "SOCKS5":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.SOCKS5,
- args.proxy_address,
- args.proxy_port,
- args.proxy_username,
- args.proxy_password))
- elif args.proxy_type == "SOCKS4":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.SOCKS4,
- args.proxy_address,
- args.proxy_port,
- args.proxy_username,
- args.proxy_password))
- elif args.proxy_type == "HTTP":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.HTTP,
- args.proxy_address,
- args.proxy_port,
- args.proxy_username,
- args.proxy_password))
- elif args.proxy_type == "MTPROTO":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- connection=
- telethon.connection.ConnectionTcpMTProxyRandomizedIntermediate,
- proxy=(args.proxy_address,
- args.proxy_port,
- args.proxy_password))
- elif os.environ.get("HTTP_PROXY"):
- http_proxy_list = os.environ["HTTP_PROXY"].split(":")
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.HTTP,
- http_proxy_list[1][2:],
- int(http_proxy_list[2]),
- args.proxy_username,
- args.proxy_password))
- else:
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash)
+ client.start()
- client.start()
+ if args.offset_day:
+ utc = pytz.UTC()
+ args.offset_day = utc.localize(
+ datetime.datetime.today() - datetime.timedelta(days=args.offset_day))
- if args.offset_day:
- utc = pytz.UTC()
- args.offset_day = utc.localize(
- datetime.datetime.today() - datetime.timedelta(days=args.offset_day))
+ if args.filter:
+ msg_filter = str_to_msg_filter(args.filter)
+ else:
+ msg_filter = None
+
+ if args.filters:
+ media_filters = []
+ for filter_str in args.filters:
+ media_filter = str_to_media_filter(filter_str)
+ if media_filter:
+ media_filters.append(media_filter)
+ else:
+ media_filters = None
- if args.filter:
- msg_filter = str_to_msg_filter(args.filter)
- else:
- msg_filter = None
+ with client:
+ client.loop.run_until_complete(iter_dialog(
+ args,
+ client,
+ msg_filter,
+ media_filters))
- if args.filters:
- media_filters = []
- for filter_str in args.filters:
- media_filter = str_to_media_filter(filter_str)
- if media_filter:
- media_filters.append(media_filter)
- else:
- media_filters = None
-
- with client:
- client.loop.run_until_complete(iter_dialog(
- args,
- client,
- msg_filter,
- media_filters))
+ except exceptions.DelethonException as err_msg:
+ if args.log_level > 0:
+ print(err_msg)
+ except KeyboardInterrupt:
+ if args.log_level > 0:
+ print(_("\nKeyboardInterrupt. Works stopped."))
return 0
diff --git a/delethon/exceptions.py b/delethon/exceptions.py
new file mode 100644
index 0000000..9976cfd
--- /dev/null
+++ b/delethon/exceptions.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+Defines exceptions used by delethon.
+"""
+
+# Import built-in modules
+import sys
+
+
+class DelethonException(Exception):
+ """
+ Raised when something need to print
+ and works need to be stopped.
+ """
+
+ def __init__(self, msg):
+ super(DelethonException, self).__init__(msg)
+ try:
+ self.msg = str(msg)
+ except UnicodeEncodeError:
+ self.msg = msg.encode(sys.stdout.encoding)
+
+ def __str__(self):
+ return self.msg
From 12960cfdbe3c99a75eae1a668cf94cb520ace243 Mon Sep 17 00:00:00 2001
From: BingLingGroup <42505588+BingLingGroup@users.noreply.github.com>
Date: Wed, 18 Mar 2020 16:22:03 +0800
Subject: [PATCH 4/4] Add option to input a group of options to avoid starting
the delethon multiple times
---
CHANGELOG.md | 18 +-
delethon/__init__.py | 478 +---------------
delethon/cmdline_utils.py | 523 ++++++++++++++++++
.../LC_MESSAGES/delethon.cmdline_utils.po | 62 +++
.../zh_CN/LC_MESSAGES/delethon.options.po | 108 ++--
.../data/locale/zh_CN/LC_MESSAGES/delethon.po | 40 +-
delethon/metadata.py | 2 +-
delethon/options.py | 24 +-
docs/CHANGELOG.zh-Hans.md | 20 +-
9 files changed, 751 insertions(+), 524 deletions(-)
create mode 100644 delethon/cmdline_utils.py
create mode 100644 delethon/data/locale/zh_CN/LC_MESSAGES/delethon.cmdline_utils.po
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99d2f43..0f7ac5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,16 +10,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## TOC
- [Unreleased](#unreleased)
- - [Added](#addedunreleased)
- - [Changed](#changedunreleased)
+- [0.1.1-alpha - 2020-03-18](#011-alpha---2020-03-18)
+ - [Added](#added011-alpha)
+ - [Changed](#changed011-alpha)
- [0.1.0-alpha - 2020-03-11](#010-alpha---2020-03-11)
- [Added](#added010-alpha)
Click up arrow to go back to TOC.
-### [Unreleased]
+### Unreleased
-#### Changed(Unreleased)
+### [0.1.1-alpha] - 2020-03-18
+
+#### Added(0.1.1-alpha)
+
+- Add option to input a group of options to avoid starting the delethon multiple times.
+
+#### Changed(0.1.1-alpha)
- Fix print bugs.
@@ -31,5 +38,6 @@ Click up arrow to go back to TOC.
↑
-[Unreleased]: https://github.com/BingLingGroup/autosub/compare/0.1.0-alpha...HEAD
+[Unreleased]: https://github.com/BingLingGroup/autosub/compare/0.1.1-alpha...HEAD
+[0.1.1-alpha]: https://github.com/BingLingGroup/autosub/compare/0.1.0-alpha...0.1.1-alpha
[0.1.0-alpha]: https://github.com/BingLingGroup/autosub/releases/tag/0.1.0-alpha
diff --git a/delethon/__init__.py b/delethon/__init__.py
index e256974..78c5f7e 100644
--- a/delethon/__init__.py
+++ b/delethon/__init__.py
@@ -5,20 +5,17 @@
"""
# Import built-in modules
-import os
-import datetime
import gettext
+import shlex
+import gc
# Import third-party modules
-import telethon
-import socks
-import pytz
-
# Any changes to the path and your own modules
from delethon import options
from delethon import constants
from delethon import exceptions
+from delethon import cmdline_utils
INIT_TEXT = gettext.translation(domain=__name__,
@@ -33,459 +30,40 @@
_ = INIT_TEXT.gettext
-async def iter_users_msg( # pylint: disable=too-many-arguments, too-many-branches
- # pylint: disable=unidiomatic-typecheck, too-many-statements
- args,
- chat_entity,
- client,
- msg_filter=None,
- media_filters=None,
- user=None):
- """
- Get or delete the message from iter_messages.
- Ref: https://docs.telethon.dev/en/latest/modules/custom.html#module-telethon.tl.custom.message
- """
- msg_count = 0
- id_user_dict = {}
- if args.log_level > 0:
- print()
- if not user:
- async for message in client.iter_messages(
- chat_entity,
- limit=args.limit,
- offset_date=args.offset_day,
- offset_id=args.offset_id,
- max_id=args.max_id,
- min_id=args.min_id,
- add_offset=args.add_offset,
- search=args.search,
- filter=msg_filter,
- wait_time=args.wait_time,
- ids=args.ids,
- reverse=args.reverse):
- if media_filters:
- if message.media:
- # https://docs.telethon.dev/en/latest/modules/custom.html#module-telethon.tl.custom.message
- # None for "convenience"
- if type(message.media) not in media_filters:
- continue
- else:
- if telethon.types.MessageMediaEmpty not in media_filters:
- continue
- if args.log_level == 0:
- await client.delete_messages(chat_entity, message.id)
- continue
- if args.log_level == 1:
- print("id: {user_id} {date}".format(
- user_id=message.from_id,
- date=message.date))
- elif args.log_level == 2:
- user_entity = id_user_dict.get(message.from_id)
- if user_entity:
- print("{first_name} {last_name}(@{username})"
- "(uid: {user_id}) {date} (mid: {msg_id})".format(
- first_name=user_entity.first_name,
- last_name=user_entity.last_name,
- username=user_entity.username,
- user_id=message.from_id,
- date=message.date,
- msg_id=message.id))
- else:
- id_user_dict[message.from_id] = await client.get_entity(message.from_id)
- print("{first_name} {last_name}(@{username})"
- "(uid: {user_id}) {date} (mid: {msg_id})".format(
- first_name=id_user_dict[message.from_id].first_name,
- last_name=id_user_dict[message.from_id].last_name,
- username=id_user_dict[message.from_id].username,
- user_id=message.from_id,
- date=message.date,
- msg_id=message.id))
- print(message.message)
- print()
- msg_count = msg_count + 1
- if not args.only_print:
- await client.delete_messages(chat_entity, message.id)
- else:
- user_entity = await client.get_entity(user)
- async for message in client.iter_messages(
- chat_entity,
- limit=args.limit,
- offset_date=args.offset_day,
- offset_id=args.offset_id,
- max_id=args.max_id,
- min_id=args.min_id,
- add_offset=args.add_offset,
- search=args.search,
- filter=msg_filter,
- wait_time=args.wait_time,
- ids=args.ids,
- reverse=args.reverse,
- from_user=user):
- if media_filters:
- if message.media:
- # https://docs.telethon.dev/en/latest/modules/custom.html#module-telethon.tl.custom.message
- # None for "convenience"
- if type(message.media) not in media_filters:
- continue
- else:
- if telethon.types.MessageMediaEmpty not in media_filters:
- continue
- if args.log_level == 0:
- await client.delete_messages(chat_entity, message.id)
- continue
- if args.log_level == 1:
- print("uid: {user_id} {date} (mid: {msg_id})".format(
- user_id=message.from_id,
- date=message.date,
- msg_id=message.id))
- elif args.log_level == 2:
- print("{first_name} {last_name}(@{username})"
- "(uid: {user_id}) {date} (mid: {msg_id})".format(
- first_name=user_entity.first_name,
- last_name=user_entity.last_name,
- username=user_entity.username,
- user_id=message.from_id,
- date=message.date,
- msg_id=message.id))
- print(message.message)
- print()
- msg_count = msg_count + 1
- if not args.only_print:
- await client.delete_messages(chat_entity, message.id)
- if args.log_level == 0:
- return 0
-
- chat = await client.get_entity(chat_entity)
-
- if isinstance(chat, telethon.types.User):
- title = chat.username
- else:
- title = chat.title
-
- if not args.only_print:
- print(_("\nDelete {msg_count} messages in chat \"{chat}\"(id: {chat_id}).").format(
- msg_count=msg_count,
- chat=title,
- chat_id=chat.id))
- else:
- print(_("\nPrint {msg_count} messages in chat \"{chat}\"(id: {chat_id}).").format(
- msg_count=msg_count,
- chat=title,
- chat_id=chat.id))
- return msg_count
-
-
-async def iter_dialog( # pylint: disable=too-many-branches, too-many-statements
- args,
- client,
- msg_filter,
- media_filters=None):
- """
- Get or delete the message from client.
- """
- user_list = []
-
- total = 0
-
- if args.me:
- user_list.append(await client.get_me())
-
- if not args.users and not user_list:
- if args.all_chats:
- async for chat_entity in client.iter_dialogs(limit=None):
- total = total + await iter_users_msg(
- args,
- chat_entity=chat_entity,
- client=client,
- msg_filter=msg_filter,
- media_filters=media_filters)
- else:
- if not args.chats:
- if args.log_level > 0:
- print("Error: No chats input.")
- return
- for chat in args.chats:
- try:
- chat_entity = await client.get_input_entity(chat)
- except ValueError as error:
- chat_entity = None
- try:
- chat_id = int(chat)
- async for dialog in client.iter_dialogs(limit=None):
- if dialog.id == chat_id:
- chat_entity = dialog
- except ValueError:
- async for dialog in client.iter_dialogs(limit=None):
- if dialog.name == chat:
- chat_entity = dialog
- if not chat_entity:
- raise error
- total = total + await iter_users_msg(
- args,
- chat_entity=chat_entity,
- client=client,
- msg_filter=msg_filter,
- media_filters=media_filters)
-
- else:
- if args.users:
- for user in args.users:
- user_entity = await client.get_input_entity(user)
- user_list.append(user_entity)
-
- if args.all_chats:
- async for chat_entity in client.iter_dialogs(limit=None):
- for user in user_list:
- total = total + await iter_users_msg(
- args,
- chat_entity=chat_entity,
- client=client,
- user=user,
- msg_filter=msg_filter,
- media_filters=media_filters)
- else:
- if not args.chats:
- if args.log_level > 0:
- print("Error: No chats input.")
- return
- for chat in args.chats:
- try:
- chat_entity = await client.get_input_entity(chat)
- except ValueError as error:
- chat_entity = None
- try:
- chat_id = int(chat)
- async for dialog in client.iter_dialogs(limit=None):
- if dialog.id == chat_id:
- chat_entity = dialog
- except ValueError:
- async for dialog in client.iter_dialogs(limit=None):
- if dialog.name == chat:
- chat_entity = dialog
- if not chat_entity:
- raise error
- for user in user_list:
- total = total + await iter_users_msg(
- args,
- chat_entity=chat_entity,
- client=client,
- user=user,
- msg_filter=msg_filter,
- media_filters=media_filters)
-
- if not args.only_print:
- if args.log_level > 0:
- print(_("Delete {msg_count} messages in total.").format(
- msg_count=total))
- else:
- print(_("Print {msg_count} messages in total.").format(
- msg_count=total))
-
-
-def str_to_msg_filter(filter_str): # pylint: disable=too-many-branches
- """
- Get types.InputMessagesFilter from filter_str
- """
- if filter_str.lower() == "chatphotos":
- msg_filter = \
- telethon.types.InputMessagesFilterChatPhotos
- elif filter_str.lower() == "contacts":
- msg_filter = \
- telethon.types.InputMessagesFilterContacts
- elif filter_str.lower() == "document":
- msg_filter = \
- telethon.types.InputMessagesFilterDocument
- elif filter_str.lower() == "empty":
- msg_filter = \
- telethon.types.InputMessagesFilterEmpty
- elif filter_str.lower() == "geo":
- msg_filter = \
- telethon.types.InputMessagesFilterGeo
- elif filter_str.lower() == "gif":
- msg_filter = \
- telethon.types.InputMessagesFilterGif
- elif filter_str.lower() == "music":
- msg_filter = \
- telethon.types.InputMessagesFilterMusic
- elif filter_str.lower() == "mentions":
- msg_filter = \
- telethon.types.InputMessagesFilterMyMentions
- elif filter_str.lower() == "phonecalls":
- msg_filter = \
- telethon.types.InputMessagesFilterPhoneCalls
- elif filter_str.lower() == "photovideo":
- msg_filter = \
- telethon.types.InputMessagesFilterPhotoVideo
- elif filter_str.lower() == "photos":
- msg_filter = \
- telethon.types.InputMessagesFilterPhotos
- elif filter_str.lower() == "roundvideo":
- msg_filter = \
- telethon.types.InputMessagesFilterRoundVideo
- elif filter_str.lower() == "roundvoice":
- msg_filter = \
- telethon.types.InputMessagesFilterRoundVoice
- elif filter_str.lower() == "url":
- msg_filter = \
- telethon.types.InputMessagesFilterUrl
- elif filter_str.lower() == "video":
- msg_filter = \
- telethon.types.InputMessagesFilterVideo
- elif filter_str.lower() == "voice":
- msg_filter = \
- telethon.types.InputMessagesFilterVoice
- else:
- msg_filter = None
-
- return msg_filter
-
-
-def str_to_media_filter(filter_str): # pylint: disable=too-many-branches
- """
- Get types.TypeMessageMedia from filter_str
- """
- if filter_str.lower() == "contact":
- media_filter = \
- telethon.types.MessageMediaContact
- elif filter_str.lower() == "document":
- media_filter = \
- telethon.types.MessageMediaDocument
- elif filter_str.lower() == "empty":
- media_filter = \
- telethon.types.MessageMediaEmpty
- elif filter_str.lower() == "game":
- media_filter = \
- telethon.types.MessageMediaGame
- elif filter_str.lower() == "geo":
- media_filter = \
- telethon.types.MessageMediaGeo
- elif filter_str.lower() == "geolive":
- media_filter = \
- telethon.types.MessageMediaGeoLive
- elif filter_str.lower() == "invoice":
- media_filter = \
- telethon.types.MessageMediaInvoice
- elif filter_str.lower() == "photo":
- media_filter = \
- telethon.types.MessageMediaPhoto
- elif filter_str.lower() == "poll":
- media_filter = \
- telethon.types.MessageMediaPoll
- elif filter_str.lower() == "unsupported":
- media_filter = \
- telethon.types.MessageMediaUnsupported
- elif filter_str.lower() == "venue":
- media_filter = \
- telethon.types.MessageMediaVenue
- elif filter_str.lower() == "webpage":
- media_filter = \
- telethon.types.MessageMediaWebPage
- else:
- media_filter = None
-
- return media_filter
-
-
def main(): # pylint: disable=too-many-branches
"""
Run delethon as a command-line program.
"""
- args = options.get_cmd_args()
-
- try:
- if not args.api_id:
- raise exceptions.DelethonException(_("Error: No api_id input."))
-
- if not args.api_hash:
- raise exceptions.DelethonException(_("Error: No api_hash input."))
-
- if args.log_level == 0 and args.only_print:
- raise exceptions.DelethonException("")
- if args.proxy_type == "SOCKS5":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.SOCKS5,
- args.proxy_address,
- args.proxy_port,
- args.proxy_username,
- args.proxy_password))
- elif args.proxy_type == "SOCKS4":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.SOCKS4,
- args.proxy_address,
- args.proxy_port,
- args.proxy_username,
- args.proxy_password))
- elif args.proxy_type == "HTTP":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.HTTP,
- args.proxy_address,
- args.proxy_port,
- args.proxy_username,
- args.proxy_password))
- elif args.proxy_type == "MTPROTO":
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- connection=
- telethon.connection.ConnectionTcpMTProxyRandomizedIntermediate,
- proxy=(args.proxy_address,
- args.proxy_port,
- args.proxy_password))
- elif os.environ.get("HTTP_PROXY"):
- http_proxy_list = os.environ["HTTP_PROXY"].split(":")
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash,
- proxy=(socks.HTTP,
- http_proxy_list[1][2:],
- int(http_proxy_list[2]),
- args.proxy_username,
- args.proxy_password))
- else:
- client = telethon.TelegramClient(
- args.session_file,
- args.api_id,
- args.api_hash)
-
- client.start()
+ parser = options.get_cmd_parser()
+ args = parser.parse_args()
- if args.offset_day:
- utc = pytz.UTC()
- args.offset_day = utc.localize(
- datetime.datetime.today() - datetime.timedelta(days=args.offset_day))
+ args_list = []
- if args.filter:
- msg_filter = str_to_msg_filter(args.filter)
- else:
- msg_filter = None
+ if args.argv:
+ for argv_str in args.argv:
+ arguments = parser.parse_args(shlex.split(argv_str))
+ args_list.append(arguments)
+ else:
+ args_list.append(args)
- if args.filters:
- media_filters = []
- for filter_str in args.filters:
- media_filter = str_to_media_filter(filter_str)
- if media_filter:
- media_filters.append(media_filter)
+ try:
+ if len(args_list) > 1:
+ last_args = args_list[0]
+ client = cmdline_utils.start_client(last_args)
+ cmdline_utils.prcs_args(last_args, client)
+ args_list = args_list[1:]
+
+ for args in args_list:
+ if not cmdline_utils.is_same_client(args, last_args):
+ del client
+ gc.collect(0)
+ client = cmdline_utils.start_client(args)
+ cmdline_utils.prcs_args(args, client)
+ last_args = args
else:
- media_filters = None
-
- with client:
- client.loop.run_until_complete(iter_dialog(
- args,
- client,
- msg_filter,
- media_filters))
+ client = cmdline_utils.start_client(args_list[0])
+ cmdline_utils.prcs_args(args_list[0], client)
except exceptions.DelethonException as err_msg:
if args.log_level > 0:
diff --git a/delethon/cmdline_utils.py b/delethon/cmdline_utils.py
new file mode 100644
index 0000000..72a68bc
--- /dev/null
+++ b/delethon/cmdline_utils.py
@@ -0,0 +1,523 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+Defines delethon's command line functionality.
+"""
+
+# Import built-in modules
+import os
+import datetime
+import gettext
+
+
+# Import third-party modules
+import telethon
+import socks
+import pytz
+
+# Any changes to the path and your own modules
+from delethon import constants
+from delethon import exceptions
+
+
+CMDLINE_UTILS_TEXT = gettext.translation(domain=__name__,
+ localedir=constants.LOCALE_PATH,
+ languages=[constants.CURRENT_LOCALE],
+ fallback=True)
+
+try:
+ _ = CMDLINE_UTILS_TEXT.ugettext
+except AttributeError:
+ # Python 3 fallback
+ _ = CMDLINE_UTILS_TEXT.gettext
+
+
+async def iter_users_msg( # pylint: disable=too-many-arguments, too-many-branches
+ # pylint: disable=unidiomatic-typecheck, too-many-statements
+ args,
+ chat_entity,
+ client,
+ msg_filter=None,
+ media_filters=None,
+ user=None):
+ """
+ Get or delete the message from iter_messages.
+ Ref: https://docs.telethon.dev/en/latest/modules/custom.html#module-telethon.tl.custom.message
+ """
+ msg_count = 0
+ id_user_dict = {}
+ if args.log_level > 0:
+ print()
+ if not user:
+ async for message in client.iter_messages(
+ chat_entity,
+ limit=args.limit,
+ offset_date=args.offset_day,
+ offset_id=args.offset_id,
+ max_id=args.max_id,
+ min_id=args.min_id,
+ add_offset=args.add_offset,
+ search=args.search,
+ filter=msg_filter,
+ wait_time=args.wait_time,
+ ids=args.ids,
+ reverse=args.reverse):
+ if media_filters:
+ if message.media:
+ # https://docs.telethon.dev/en/latest/modules/custom.html#module-telethon.tl.custom.message
+ # None for "convenience"
+ if type(message.media) not in media_filters:
+ continue
+ else:
+ if telethon.types.MessageMediaEmpty not in media_filters:
+ continue
+ if args.log_level == 0:
+ await client.delete_messages(chat_entity, message.id)
+ continue
+ if args.log_level == 1:
+ print("id: {user_id} {date}".format(
+ user_id=message.from_id,
+ date=message.date))
+ elif args.log_level == 2:
+ user_entity = id_user_dict.get(message.from_id)
+ if user_entity:
+ print("{first_name} {last_name}(@{username})"
+ "(uid: {user_id}) {date} (mid: {msg_id})".format(
+ first_name=user_entity.first_name,
+ last_name=user_entity.last_name,
+ username=user_entity.username,
+ user_id=message.from_id,
+ date=message.date,
+ msg_id=message.id))
+ else:
+ id_user_dict[message.from_id] = await client.get_entity(message.from_id)
+ print("{first_name} {last_name}(@{username})"
+ "(uid: {user_id}) {date} (mid: {msg_id})".format(
+ first_name=id_user_dict[message.from_id].first_name,
+ last_name=id_user_dict[message.from_id].last_name,
+ username=id_user_dict[message.from_id].username,
+ user_id=message.from_id,
+ date=message.date,
+ msg_id=message.id))
+ print(message.message)
+ print()
+ msg_count = msg_count + 1
+ if not args.only_print:
+ await client.delete_messages(chat_entity, message.id)
+ else:
+ user_entity = await client.get_entity(user)
+ async for message in client.iter_messages(
+ chat_entity,
+ limit=args.limit,
+ offset_date=args.offset_day,
+ offset_id=args.offset_id,
+ max_id=args.max_id,
+ min_id=args.min_id,
+ add_offset=args.add_offset,
+ search=args.search,
+ filter=msg_filter,
+ wait_time=args.wait_time,
+ ids=args.ids,
+ reverse=args.reverse,
+ from_user=user):
+ if media_filters:
+ if message.media:
+ # https://docs.telethon.dev/en/latest/modules/custom.html#module-telethon.tl.custom.message
+ # None for "convenience"
+ if type(message.media) not in media_filters:
+ continue
+ else:
+ if telethon.types.MessageMediaEmpty not in media_filters:
+ continue
+ if args.log_level == 0:
+ await client.delete_messages(chat_entity, message.id)
+ continue
+ if args.log_level == 1:
+ print("uid: {user_id} {date} (mid: {msg_id})".format(
+ user_id=message.from_id,
+ date=message.date,
+ msg_id=message.id))
+ elif args.log_level == 2:
+ print("{first_name} {last_name}(@{username})"
+ "(uid: {user_id}) {date} (mid: {msg_id})".format(
+ first_name=user_entity.first_name,
+ last_name=user_entity.last_name,
+ username=user_entity.username,
+ user_id=message.from_id,
+ date=message.date,
+ msg_id=message.id))
+ print(message.message)
+ print()
+ msg_count = msg_count + 1
+ if not args.only_print:
+ await client.delete_messages(chat_entity, message.id)
+ if args.log_level == 0:
+ return 0
+
+ chat = await client.get_entity(chat_entity)
+
+ if isinstance(chat, telethon.types.User):
+ title = "@{}".format(chat.username)
+ else:
+ title = chat.title
+
+ if not args.only_print:
+ print(_("\nDelete {msg_count} messages in chat \"{chat}\"(id: {chat_id}).").format(
+ msg_count=msg_count,
+ chat=title,
+ chat_id=chat.id))
+ else:
+ print(_("\nPrint {msg_count} messages in chat \"{chat}\"(id: {chat_id}).").format(
+ msg_count=msg_count,
+ chat=title,
+ chat_id=chat.id))
+ return msg_count
+
+
+async def iter_dialog( # pylint: disable=too-many-branches, too-many-statements
+ args,
+ client,
+ msg_filter,
+ media_filters=None):
+ """
+ Get or delete the message from client.
+ """
+ user_list = []
+ total = 0
+ meme = None
+
+ if args.log_level > 1:
+ meme = await client.get_me()
+ print(_("\nCurrent login user: "
+ "{first_name} {last_name}(@{username})").format(
+ first_name=meme.first_name,
+ last_name=meme.last_name,
+ username=meme.username))
+
+ if args.me:
+ if not meme:
+ meme = await client.get_me()
+ user_list.append(meme)
+
+ if not args.users and not user_list:
+ if args.all_chats:
+ async for chat_entity in client.iter_dialogs(limit=None):
+ total = total + await iter_users_msg(
+ args,
+ chat_entity=chat_entity,
+ client=client,
+ msg_filter=msg_filter,
+ media_filters=media_filters)
+ else:
+ if not args.chats:
+ if args.log_level > 0:
+ print(_("Error: No chats input."))
+ return
+ for chat in args.chats:
+ try:
+ chat_entity = await client.get_input_entity(chat)
+ except ValueError as error:
+ chat_entity = None
+ try:
+ chat_id = int(chat)
+ async for dialog in client.iter_dialogs(limit=None):
+ if dialog.id == chat_id:
+ chat_entity = dialog
+ except ValueError:
+ async for dialog in client.iter_dialogs(limit=None):
+ if dialog.name == chat:
+ chat_entity = dialog
+ if not chat_entity:
+ raise error
+ total = total + await iter_users_msg(
+ args,
+ chat_entity=chat_entity,
+ client=client,
+ msg_filter=msg_filter,
+ media_filters=media_filters)
+
+ else:
+ if args.users:
+ for user in args.users:
+ user_entity = await client.get_input_entity(user)
+ user_list.append(user_entity)
+
+ if args.all_chats:
+ async for chat_entity in client.iter_dialogs(limit=None):
+ for user in user_list:
+ total = total + await iter_users_msg(
+ args,
+ chat_entity=chat_entity,
+ client=client,
+ user=user,
+ msg_filter=msg_filter,
+ media_filters=media_filters)
+ else:
+ if not args.chats:
+ if args.log_level > 0:
+ print(_("Error: No chats input."))
+ return
+ for chat in args.chats:
+ try:
+ chat_entity = await client.get_input_entity(chat)
+ except ValueError as error:
+ chat_entity = None
+ try:
+ chat_id = int(chat)
+ async for dialog in client.iter_dialogs(limit=None):
+ if dialog.id == chat_id:
+ chat_entity = dialog
+ except ValueError:
+ async for dialog in client.iter_dialogs(limit=None):
+ if dialog.name == chat:
+ chat_entity = dialog
+ if not chat_entity:
+ raise error
+ for user in user_list:
+ total = total + await iter_users_msg(
+ args,
+ chat_entity=chat_entity,
+ client=client,
+ user=user,
+ msg_filter=msg_filter,
+ media_filters=media_filters)
+
+ if not args.only_print:
+ if args.log_level > 0:
+ print(_("Delete {msg_count} messages in total.").format(
+ msg_count=total))
+ else:
+ print(_("Print {msg_count} messages in total.").format(
+ msg_count=total))
+
+
+def str_to_msg_filter(filter_str): # pylint: disable=too-many-branches
+ """
+ Get types.InputMessagesFilter from filter_str
+ """
+ if filter_str.lower() == "chatphotos":
+ msg_filter = \
+ telethon.types.InputMessagesFilterChatPhotos
+ elif filter_str.lower() == "contacts":
+ msg_filter = \
+ telethon.types.InputMessagesFilterContacts
+ elif filter_str.lower() == "document":
+ msg_filter = \
+ telethon.types.InputMessagesFilterDocument
+ elif filter_str.lower() == "empty":
+ msg_filter = \
+ telethon.types.InputMessagesFilterEmpty
+ elif filter_str.lower() == "geo":
+ msg_filter = \
+ telethon.types.InputMessagesFilterGeo
+ elif filter_str.lower() == "gif":
+ msg_filter = \
+ telethon.types.InputMessagesFilterGif
+ elif filter_str.lower() == "music":
+ msg_filter = \
+ telethon.types.InputMessagesFilterMusic
+ elif filter_str.lower() == "mentions":
+ msg_filter = \
+ telethon.types.InputMessagesFilterMyMentions
+ elif filter_str.lower() == "phonecalls":
+ msg_filter = \
+ telethon.types.InputMessagesFilterPhoneCalls
+ elif filter_str.lower() == "photovideo":
+ msg_filter = \
+ telethon.types.InputMessagesFilterPhotoVideo
+ elif filter_str.lower() == "photos":
+ msg_filter = \
+ telethon.types.InputMessagesFilterPhotos
+ elif filter_str.lower() == "roundvideo":
+ msg_filter = \
+ telethon.types.InputMessagesFilterRoundVideo
+ elif filter_str.lower() == "roundvoice":
+ msg_filter = \
+ telethon.types.InputMessagesFilterRoundVoice
+ elif filter_str.lower() == "url":
+ msg_filter = \
+ telethon.types.InputMessagesFilterUrl
+ elif filter_str.lower() == "video":
+ msg_filter = \
+ telethon.types.InputMessagesFilterVideo
+ elif filter_str.lower() == "voice":
+ msg_filter = \
+ telethon.types.InputMessagesFilterVoice
+ else:
+ msg_filter = None
+
+ return msg_filter
+
+
+def str_to_media_filter(filter_str): # pylint: disable=too-many-branches
+ """
+ Get types.TypeMessageMedia from filter_str
+ """
+ if filter_str.lower() == "contact":
+ media_filter = \
+ telethon.types.MessageMediaContact
+ elif filter_str.lower() == "document":
+ media_filter = \
+ telethon.types.MessageMediaDocument
+ elif filter_str.lower() == "empty":
+ media_filter = \
+ telethon.types.MessageMediaEmpty
+ elif filter_str.lower() == "game":
+ media_filter = \
+ telethon.types.MessageMediaGame
+ elif filter_str.lower() == "geo":
+ media_filter = \
+ telethon.types.MessageMediaGeo
+ elif filter_str.lower() == "geolive":
+ media_filter = \
+ telethon.types.MessageMediaGeoLive
+ elif filter_str.lower() == "invoice":
+ media_filter = \
+ telethon.types.MessageMediaInvoice
+ elif filter_str.lower() == "photo":
+ media_filter = \
+ telethon.types.MessageMediaPhoto
+ elif filter_str.lower() == "poll":
+ media_filter = \
+ telethon.types.MessageMediaPoll
+ elif filter_str.lower() == "unsupported":
+ media_filter = \
+ telethon.types.MessageMediaUnsupported
+ elif filter_str.lower() == "venue":
+ media_filter = \
+ telethon.types.MessageMediaVenue
+ elif filter_str.lower() == "webpage":
+ media_filter = \
+ telethon.types.MessageMediaWebPage
+ else:
+ media_filter = None
+
+ return media_filter
+
+
+def start_client(args):
+ """
+ Use args to create client.
+ """
+ if not args.api_id:
+ raise exceptions.DelethonException(_("Error: No api_id input."))
+
+ if not args.api_hash:
+ raise exceptions.DelethonException(_("Error: No api_hash input."))
+
+ if args.log_level == 0 and args.only_print:
+ raise exceptions.DelethonException("")
+
+ if args.proxy_type == "SOCKS5":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.SOCKS5,
+ args.proxy_address,
+ args.proxy_port,
+ args.proxy_username,
+ args.proxy_password))
+ elif args.proxy_type == "SOCKS4":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.SOCKS4,
+ args.proxy_address,
+ args.proxy_port,
+ args.proxy_username,
+ args.proxy_password))
+ elif args.proxy_type == "HTTP":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.HTTP,
+ args.proxy_address,
+ args.proxy_port,
+ args.proxy_username,
+ args.proxy_password))
+ elif args.proxy_type == "MTPROTO":
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ connection=
+ telethon.connection.ConnectionTcpMTProxyRandomizedIntermediate,
+ proxy=(args.proxy_address,
+ args.proxy_port,
+ args.proxy_password))
+ elif os.environ.get("HTTP_PROXY"):
+ http_proxy_list = os.environ["HTTP_PROXY"].split(":")
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash,
+ proxy=(socks.HTTP,
+ http_proxy_list[1][2:],
+ int(http_proxy_list[2]),
+ args.proxy_username,
+ args.proxy_password))
+ else:
+ client = telethon.TelegramClient(
+ args.session_file,
+ args.api_id,
+ args.api_hash)
+
+ client.start()
+
+ return client
+
+
+def prcs_args(args, client):
+ """
+ Process delethon's args.
+ """
+ if args.offset_day:
+ utc = pytz.UTC()
+ args.offset_day = utc.localize(
+ datetime.datetime.today() - datetime.timedelta(days=args.offset_day))
+
+ if args.filter:
+ msg_filter = str_to_msg_filter(args.filter)
+ else:
+ msg_filter = None
+
+ if args.filters:
+ media_filters = []
+ for filter_str in args.filters:
+ media_filter = str_to_media_filter(filter_str)
+ if media_filter:
+ media_filters.append(media_filter)
+ else:
+ media_filters = None
+
+ with client:
+ client.loop.run_until_complete(iter_dialog(
+ args,
+ client,
+ msg_filter,
+ media_filters))
+
+
+def is_same_client(args, last_args):
+ """
+ Check if the two args can use the same client.
+ """
+ if not args.api_id or not args.api_hash:
+ args.api_id = last_args.api_id
+ args.api_hash = last_args.api_hash
+ args.session_file = last_args.session_file
+
+ if args.api_id == last_args.api_id\
+ and args.api_hash == last_args.api_hash\
+ and args.proxy_type == last_args.proxy_type\
+ and args.proxy_address == last_args.proxy_address\
+ and args.proxy_port == last_args.proxy_port:
+ if args.proxy_username == last_args.proxy_username\
+ and args.proxy_password == last_args.proxy_password\
+ and args.session_file == last_args.session_file:
+ return True
+
+ return False
diff --git a/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.cmdline_utils.po b/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.cmdline_utils.po
new file mode 100644
index 0000000..a0d1bd6
--- /dev/null
+++ b/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.cmdline_utils.po
@@ -0,0 +1,62 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-03-18 16:16+0800\n"
+"PO-Revision-Date: 2020-03-18 15:45+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 2.3\n"
+
+#: delethon/cmdline_utils.py:165
+msgid ""
+"\n"
+"Delete {msg_count} messages in chat \"{chat}\"(id: {chat_id})."
+msgstr ""
+"\n"
+"在聊天“{chat}”(id: {chat_id})中删除{msg_count}个消息。"
+
+#: delethon/cmdline_utils.py:170
+msgid ""
+"\n"
+"Print {msg_count} messages in chat \"{chat}\"(id: {chat_id})."
+msgstr ""
+"\n"
+"在聊天“{chat}”(id: {chat_id})中输出{msg_count}个消息。"
+
+#: delethon/cmdline_utils.py:191
+msgid ""
+"\n"
+"Current login user: {first_name} {last_name}(@{username})"
+msgstr ""
+"\n"
+"当前登录用户:{first_name} {last_name}(@{username})"
+
+#: delethon/cmdline_utils.py:214 delethon/cmdline_utils.py:258
+msgid "Error: No chats input."
+msgstr "错误:没有输入对话信息。"
+
+#: delethon/cmdline_utils.py:287
+msgid "Delete {msg_count} messages in total."
+msgstr "总共删除了{msg_count}个消息。"
+
+#: delethon/cmdline_utils.py:290
+msgid "Print {msg_count} messages in total."
+msgstr "总共输出了{msg_count}个消息。"
+
+#: delethon/cmdline_utils.py:403
+msgid "Error: No api_id input."
+msgstr "错误:没有api_id输入。"
+
+#: delethon/cmdline_utils.py:406
+msgid "Error: No api_hash input."
+msgstr "错误:没有api_hash输入。"
diff --git a/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.options.po b/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.options.po
index 579a06d..c94c7c5 100644
--- a/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.options.po
+++ b/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.options.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-03-11 12:19+0800\n"
-"PO-Revision-Date: 2020-03-11 12:20+0800\n"
+"POT-Creation-Date: 2020-03-18 16:16+0800\n"
+"PO-Revision-Date: 2020-03-18 16:16+0800\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -92,7 +92,15 @@ msgstr "信息选项"
msgid "Options to get extra information."
msgstr "用于获取额外信息的选项。"
-#: delethon/options.py:87
+#: delethon/options.py:83
+msgid "Group Options"
+msgstr "组选项"
+
+#: delethon/options.py:84
+msgid "Options to input group of arguments."
+msgstr "用于输入一组参数的选项。"
+
+#: delethon/options.py:92
#, python-format
msgid ""
"Telegram app api_id. Input it or set the environment variable "
@@ -102,7 +110,7 @@ msgstr ""
"Telegram应用api_id。输入它或者设置环境变量“TELEGRAM_API_ID”。你能从https://"
"my.telegram.org/apps中获得一个。(参数个数为1)(默认参数为%(default)s)"
-#: delethon/options.py:97
+#: delethon/options.py:102
#, python-format
msgid ""
"Telegram app api_hash. Input it or set the environment variable "
@@ -113,11 +121,11 @@ msgstr ""
"https://my.telegram.org/apps中获得一个。(参数个数为1)(默认参数"
"为%(default)s)"
-#: delethon/options.py:105
+#: delethon/options.py:110
msgid "path"
msgstr "路径"
-#: delethon/options.py:107
+#: delethon/options.py:112
#, python-format
msgid ""
"Telegram session file path. Ref: https://docs.telethon.dev/en/latest/"
@@ -126,11 +134,11 @@ msgstr ""
"Telegram会话文件路径。参考:https://docs.telethon.dev/en/latest/concepts/"
"sessions.html(参数个数为1)(默认参数为%(default)s)"
-#: delethon/options.py:114
+#: delethon/options.py:119
msgid "proxy_type"
msgstr "代理类型"
-#: delethon/options.py:117
+#: delethon/options.py:122
#, python-format
msgid ""
"PySocks or MTProto Proxy. Available types: \"SOCKS5\", \"SOCKS4\", \"HTTP\", "
@@ -148,11 +156,11 @@ msgstr ""
"a-proxy 如果参数个数是0,使用const类型。(参数个数为0或1)(const"
"为%(const)s)"
-#: delethon/options.py:133
+#: delethon/options.py:138
msgid "address"
msgstr "地址"
-#: delethon/options.py:135
+#: delethon/options.py:140
#, python-format
msgid ""
"The IP address or DNS name of the proxy server. (arg_num = 1) (default: "
@@ -160,28 +168,28 @@ msgid ""
msgstr ""
"IP地址或者代理服务器的DNS名称。(参数个数为1)(默认参数为%(default)s)"
-#: delethon/options.py:141
+#: delethon/options.py:146
msgid "port"
msgstr "端口"
-#: delethon/options.py:144
+#: delethon/options.py:149
#, python-format
msgid "The port of the proxy server. (arg_num = 1) (default: %(default)s)"
msgstr "代理服务器的端口。(参数个数为1)(默认参数为%(default)s)"
-#: delethon/options.py:150
+#: delethon/options.py:155
msgid "username"
msgstr "用户名"
-#: delethon/options.py:151
+#: delethon/options.py:156
msgid "Set proxy username. (arg_num = 1)"
msgstr "设置代理用户名。(参数个数为1)"
-#: delethon/options.py:157
+#: delethon/options.py:162
msgid "password"
msgstr "密码"
-#: delethon/options.py:158
+#: delethon/options.py:163
msgid ""
"Set proxy password. When using \"MTPROTO\", this option is \"secret\" "
"instead. (arg_num = 1)"
@@ -189,11 +197,11 @@ msgstr ""
"设置代理密码。如果使用\"MTPROTO\",这个参数则会代表\"secret\"。(参数个数为"
"1)"
-#: delethon/options.py:166 delethon/options.py:179
+#: delethon/options.py:171 delethon/options.py:184
msgid "entity_like"
msgstr "实体类"
-#: delethon/options.py:167
+#: delethon/options.py:172
msgid ""
"Get the messages in the chat entity/entities. entity_like can be Telegram "
"username, Group name and so on. If failed to get one, it will use it to "
@@ -206,7 +214,7 @@ msgstr ""
"参考:https://docs.telethon.dev/en/latest/concepts/entities.html#getting-"
"entities(参数个数大于等于1)"
-#: delethon/options.py:180
+#: delethon/options.py:185
msgid ""
"Get the messages from the user entity/entities. If not input, gets all users "
"messages. Ref: https://docs.telethon.dev/en/latest/concepts/entities."
@@ -216,23 +224,23 @@ msgstr ""
"考https://docs.telethon.dev/en/latest/concepts/entities.html#getting-"
"entities(参数个数大于等于1)"
-#: delethon/options.py:190
+#: delethon/options.py:195
msgid "Get messages from the current user who is logged in. (arg_num = 0)"
msgstr "获取当前登录用户发送的消息。(参数个数为0)"
-#: delethon/options.py:196
+#: delethon/options.py:201
msgid ""
"Iterate over all the chat entity/entities that the current user joined. "
"(arg_num = 0)"
msgstr "获得当前登录用户参加的所有对话实体。(参数个数为0)"
-#: delethon/options.py:202 delethon/options.py:213 delethon/options.py:222
-#: delethon/options.py:233 delethon/options.py:243 delethon/options.py:253
-#: delethon/options.py:285 delethon/options.py:299 delethon/options.py:349
+#: delethon/options.py:207 delethon/options.py:218 delethon/options.py:227
+#: delethon/options.py:238 delethon/options.py:248 delethon/options.py:258
+#: delethon/options.py:290 delethon/options.py:304 delethon/options.py:354
msgid "int"
msgstr "整数"
-#: delethon/options.py:204
+#: delethon/options.py:209
msgid ""
"Number of messages to be retrieved. Slower when more than 3000. Ref: https://"
"docs.telethon.dev/en/latest/modules/client.html#telethon.client.messages."
@@ -242,43 +250,43 @@ msgstr ""
"latest/modules/client.html#telethon.client.messages.MessageMethods."
"iter_messages (参数个数为1)(默认不限制数量)"
-#: delethon/options.py:215
+#: delethon/options.py:220
msgid ""
"Offset day (messages previous to this day will be retrieved). Exclusive. "
"(arg_num = 1)"
msgstr "偏移日期(比这天早的消息会被取回)。独占性。(参数个数为1)"
-#: delethon/options.py:225
+#: delethon/options.py:230
msgid ""
"Offset message ID (only messages previous to the given ID will be "
"retrieved). Exclusive. (arg_num = 1)"
msgstr ""
"偏移消息ID(只有比这个ID更早的消息才会被取回)。独占性。(参数个数为1)"
-#: delethon/options.py:236
+#: delethon/options.py:241
msgid ""
"All the messages with a higher (newer) ID or equal to this will be excluded. "
"(arg_num = 1)"
msgstr "所有比这个ID数值更高也就是更新的消息会被排除。(参数个数为1)"
-#: delethon/options.py:246
+#: delethon/options.py:251
msgid ""
"All the messages with a lower (older) ID or equal to this will be excluded. "
"(arg_num = 1)"
msgstr "所有比这个ID数值更小也就是更旧的消息会被排除。(参数个数为1)"
-#: delethon/options.py:256
+#: delethon/options.py:261
msgid ""
"Additional message offset (all of the specified offsets + this offset = "
"older messages). (arg_num = 1)"
msgstr ""
"额外消息偏移(所有制ID那个的偏移加上这个偏移=更旧的消息)。(参数个数为1)"
-#: delethon/options.py:263
+#: delethon/options.py:268
msgid "str"
msgstr "字符串"
-#: delethon/options.py:264
+#: delethon/options.py:269
msgid ""
"The string to be used as a search query. Give the same result as other "
"Telegram official clients meaning it's not optimized for some non-English "
@@ -287,11 +295,11 @@ msgstr ""
"用来搜索的字符串。和其他Telegram官方客户端得到的搜索结果一样,意味着对部分非"
"英语语言未做优化。(参数个数为1)"
-#: delethon/options.py:272 delethon/options.py:334
+#: delethon/options.py:277 delethon/options.py:339
msgid "type"
msgstr "类型"
-#: delethon/options.py:273
+#: delethon/options.py:278
msgid ""
"The filter to use before returning messages. For instance, \"photos\" for "
"\"InputMessagesFilterPhotos\" would yield only messages containing photos. "
@@ -306,7 +314,7 @@ msgstr ""
"geo, gif, music, mentions, phonecalls, photovideo, photos, roundvideo, "
"roundvoice, url, video, voice(参数个数为1)"
-#: delethon/options.py:287
+#: delethon/options.py:292
msgid ""
"Wait time (in seconds) between different GetHistoryRequest. Use this "
"parameter to avoid hitting the FloodWaitError as needed. If left to None, it "
@@ -318,7 +326,7 @@ msgstr ""
"FloodWaitError。如果不输入,超过3000个消息时的等待默认为1秒。如果id参数使用"
"了,id超过300时,这个时间将被设置为10秒。(参数个数为1)"
-#: delethon/options.py:302
+#: delethon/options.py:307
msgid ""
"A single integer ID (or several IDs) for the message that should be "
"returned. This parameter takes precedence over the rest (which will be "
@@ -331,7 +339,7 @@ msgstr ""
"条消息。注意如果消息不存在,会返回None,所以将包含ID的列表压缩在一起能得到一"
"对一的结果。(参数个数大于等于1)"
-#: delethon/options.py:316
+#: delethon/options.py:321
msgid ""
"The messages will be returned in reverse order (from oldest to newest, "
"instead of the default newest to oldest). This also means that the meaning "
@@ -345,11 +353,11 @@ msgstr ""
"的。 同样地,\"--min-id\"等效于\"--offset-id\"而非\"--max-id\"因为消息会按照"
"升序返回。(参数个数为0)"
-#: delethon/options.py:328
+#: delethon/options.py:333
msgid "Only print message instead of deleting them. (arg_num = 0)"
msgstr "只在屏幕上输出消息而非删除他们。(参数个数为0)"
-#: delethon/options.py:335
+#: delethon/options.py:340
msgid ""
"The filters to use after returning the messages from \"iter_messages\". So "
"using it will delete equal to or less amount of messages than the argument "
@@ -366,7 +374,7 @@ msgstr ""
"unsupported, venue, webpage 参考:https://tl.telethon.dev/types/"
"message_media.html(参数个数大于等于1)"
-#: delethon/options.py:353
+#: delethon/options.py:358
#, python-format
msgid ""
"Print different kinds of messages. 0 for nothing. 1 for basic. 2 for more "
@@ -375,15 +383,31 @@ msgstr ""
"在屏幕上输出不同类别的消息。0为不输出。1为基本信息。2则是更多的信息。(参数个"
"数为1)(默认参数为%(default)s)"
-#: delethon/options.py:360
+#: delethon/options.py:365
#, python-format
msgid "Show %(prog)s help message and exit. (arg_num = 0)"
msgstr "显示%(prog)s的帮助信息并退出。(参数个数为0)"
-#: delethon/options.py:368
+#: delethon/options.py:373
#, python-format
msgid "Show %(prog)s version and exit. (arg_num = 0)"
msgstr "显示%(prog)s的版本信息并退出。(参数个数为0)"
+#: delethon/options.py:378
+msgid "option_group"
+msgstr "一组选项"
+
+#: delethon/options.py:379
+msgid ""
+"A group of options to input to avoid starting the delethon multiple times. "
+"Except for the first group, if the group options don't include \"-ai\" or \"-"
+"ah\", it will avoid starting the client multiple times to avoid extra "
+"consumption. Remember to input the group of options in quotes and escape the "
+"original quotes by using backslash \"\\\". (arg_num >= 1)"
+msgstr ""
+"输入一组选项来避免反复运行delethon。除了第一组参数,如果参数没有包含\"-ai\"和"
+"\"-ah\",它会避免重复启动客户端带来的额外消耗。输入一组选项时,需要用引号包"
+"围,并且要把原先的引号用反斜线\"\\\"转义。(参数个数大于等于1)"
+
#~ msgid "Operation Options"
#~ msgstr "操作选项"
diff --git a/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.po b/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.po
index 7f9f4f4..4b8a00b 100644
--- a/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.po
+++ b/delethon/data/locale/zh_CN/LC_MESSAGES/delethon.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-03-10 17:32+0800\n"
-"PO-Revision-Date: 2020-03-10 17:33+0800\n"
+"POT-Creation-Date: 2020-03-18 15:39+0800\n"
+"PO-Revision-Date: 2020-03-18 11:33+0800\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -17,26 +17,30 @@ msgstr ""
"Language: zh_CN\n"
"X-Generator: Poedit 2.3\n"
-#: delethon/__init__.py:163
+#: delethon/__init__.py:73
msgid ""
"\n"
-"Delete {msg_count} messages in chat \"{chat}\"(id: {chat_id})."
+"KeyboardInterrupt. Works stopped."
msgstr ""
"\n"
-"在聊天“{chat}”(id: {chat_id})中删除{msg_count}个消息。"
+"键盘中断。操作终止。"
-#: delethon/__init__.py:168
-msgid ""
-"\n"
-"Print {msg_count} messages in chat \"{chat}\"(id: {chat_id})."
-msgstr ""
-"\n"
-"在聊天“{chat}”(id: {chat_id})中输出{msg_count}个消息。"
+#~ msgid ""
+#~ "\n"
+#~ "Delete {msg_count} messages in chat \"{chat}\"(id: {chat_id})."
+#~ msgstr ""
+#~ "\n"
+#~ "在聊天“{chat}”(id: {chat_id})中删除{msg_count}个消息。"
+
+#~ msgid ""
+#~ "\n"
+#~ "Print {msg_count} messages in chat \"{chat}\"(id: {chat_id})."
+#~ msgstr ""
+#~ "\n"
+#~ "在聊天“{chat}”(id: {chat_id})中输出{msg_count}个消息。"
-#: delethon/__init__.py:229
-msgid "Delete {msg_count} messages in total."
-msgstr "总共删除了{msg_count}个消息。"
+#~ msgid "Delete {msg_count} messages in total."
+#~ msgstr "总共删除了{msg_count}个消息。"
-#: delethon/__init__.py:232
-msgid "Print {msg_count} messages in total."
-msgstr "总共输出了{msg_count}个消息。"
+#~ msgid "Print {msg_count} messages in total."
+#~ msgstr "总共输出了{msg_count}个消息。"
diff --git a/delethon/metadata.py b/delethon/metadata.py
index 677bf99..ec3f005 100644
--- a/delethon/metadata.py
+++ b/delethon/metadata.py
@@ -7,7 +7,7 @@
_ = str
NAME = 'delethon'
-VERSION = '0.1.0-alpha'
+VERSION = '0.1.1-alpha'
DESCRIPTION = _('Delete Telegram messages based on Telethon.')
AUTHOR = 'Bing Ling'
AUTHOR_EMAIL = 'binglinggroup@outlook.com'
diff --git a/delethon/options.py b/delethon/options.py
index 6acf409..8bd63cc 100644
--- a/delethon/options.py
+++ b/delethon/options.py
@@ -31,7 +31,7 @@
M_ = META_TEXT.gettext
-def get_cmd_args():
+def get_cmd_parser():
"""
Get command-line arguments.
"""
@@ -79,6 +79,11 @@ def get_cmd_args():
_('Options to get extra information.')
)
+ options_group = parser.add_argument_group(
+ _('Group Options'),
+ _('Options to input group of arguments.')
+ )
+
client_group.add_argument(
'-ai', '--api-id',
metavar='API_ID',
@@ -367,4 +372,19 @@ def get_cmd_args():
+ metadata.AUTHOR_EMAIL + '>',
help=_("Show %(prog)s version and exit. (arg_num = 0)"))
- return parser.parse_args()
+ options_group.add_argument(
+ '-a', '--argv',
+ nargs=argparse.REMAINDER,
+ metavar=_('option_group'),
+ help=_("A group of options to input to "
+ "avoid starting the delethon multiple times. "
+ "Except for the first group, "
+ "if the group options don't include \"-ai\" or \"-ah\", "
+ "it will avoid starting the client multiple times "
+ "to avoid extra consumption. "
+ "Remember to input the group of options in quotes "
+ "and escape the original quotes by using backslash \"\\\". "
+ "(arg_num >= 1)")
+ )
+
+ return parser
diff --git a/docs/CHANGELOG.zh-Hans.md b/docs/CHANGELOG.zh-Hans.md
index 25b1cfb..c5a2565 100644
--- a/docs/CHANGELOG.zh-Hans.md
+++ b/docs/CHANGELOG.zh-Hans.md
@@ -9,8 +9,9 @@
## 目录
- [未发布](#未发布)
- - [添加](#添加未发布)
- - [修改](#修改未发布)
+- [0.1.1-alpha - 2020-03-18](#011-alpha---2020-03-18)
+ - [添加](#添加011-alpha)
+ - [修改](#修改011-alpha)
- [0.1.0-alpha - 2020-03-11](#010-alpha---2020-03-11)
- [添加](#添加010-alpha)
@@ -18,7 +19,13 @@
### [未发布]
-#### 修改(未发布)
+### [0.1.1-alpha] - 2020-03-18
+
+#### 添加(0.1.1-alpha)
+
+- 添加选项允许输入一组选项来避免delethon的反复启动。
+
+#### 修改(0.1.1-alpha)
- 修复输出问题。
@@ -28,7 +35,8 @@
- 添加基本消息删除功能。
- ↑
+ ↑
-[Unreleased]: https://github.com/BingLingGroup/autosub/compare/0.1.0-alpha...HEAD
-[0.1.0-alpha]: https://github.com/BingLingGroup/autosub/releases/tag/0.1.0-alpha
+[Unreleased]: https://github.com/BingLingGroup/autosub/compare/0.1.1-alpha...HEAD
+[0.1.1-alpha]: https://github.com/BingLingGroup/autosub/compare/0.1.0-alpha...0.1.1-alpha
+[0.1.0-alpha]: https://github.com/BingLingGroup/autosub/releases/tag/0.1.0-alpha
\ No newline at end of file