PyPtt 2.2.4__tar.gz → 2.2.5__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.
- {pyptt-2.2.4 → pyptt-2.2.5}/PKG-INFO +1 -1
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/PTT.py +33 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/__init__.py +1 -1
- pyptt-2.2.5/PyPtt/_api_set_signature_file.py +86 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/lang_en_US.py +1 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/lang_zh_TW.py +1 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt.egg-info/PKG-INFO +1 -1
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt.egg-info/SOURCES.txt +2 -0
- pyptt-2.2.5/tests/test_set_signature_file.py +32 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/LICENSE +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_bucket.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_call_status.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_change_pw.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_comment.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_del_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_board_info.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_board_list.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_bottom_post_list.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_favourite_board.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_newest_index.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_post_index.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_post_list.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_time.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_user.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_get_waterball.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_give_money.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_has_new_mail.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_loginout.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_lottery.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_mail.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_mark_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_reply_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_search_user.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_set_board_title.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_api_util.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_uao/LICENSE +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_uao/__init__.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_uao/b2u.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/_uao/u2b.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/api_server.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/check_value.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/command.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/config.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/connect_core.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/data_type.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/exceptions.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/i18n.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/lib_util.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/log.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/screens.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/service.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt/ssl_config.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt.egg-info/dependency_links.txt +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt.egg-info/requires.txt +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/PyPtt.egg-info/top_level.txt +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/README.md +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/pyproject.toml +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/setup.cfg +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/setup.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_bucket.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_change_pw.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_comment.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_del_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_del_post_unit.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_exceptions.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_fast_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_board_info.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_board_list.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_bottom_post_list.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_content_formula.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_favourite_boards.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_mail.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_newest_index.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_post_list.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_post_list_parser.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_post_parser.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_time.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_user.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_get_waterball.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_give_money.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_i18n.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_init.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_logger.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_login_logout.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_lottery.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_mail_send_and_del.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_mark_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_parse_query_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_post_anonymous.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_pyte_parity.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_reply_post.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_search_user.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_service.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_set_board_title.py +0 -0
- {pyptt-2.2.4 → pyptt-2.2.5}/tests/test_vt100_parser.py +0 -0
|
@@ -28,6 +28,7 @@ from . import _api_post
|
|
|
28
28
|
from . import _api_reply_post
|
|
29
29
|
from . import _api_search_user
|
|
30
30
|
from . import _api_set_board_title
|
|
31
|
+
from . import _api_set_signature_file
|
|
31
32
|
from . import check_value
|
|
32
33
|
from . import config
|
|
33
34
|
from . import connect_core
|
|
@@ -806,6 +807,38 @@ class API:
|
|
|
806
807
|
|
|
807
808
|
_api_set_board_title.set_board_title(self, board, new_title)
|
|
808
809
|
|
|
810
|
+
def set_signature_file(self, content: str) -> None:
|
|
811
|
+
|
|
812
|
+
"""
|
|
813
|
+
更新登入帳號的名片檔(PTT 的 plan),對應【個人設定】->【個人檔案】
|
|
814
|
+
->(Q)ueryEdit 編輯名片檔的功能。`get_user()` 回傳的 `signature_file`
|
|
815
|
+
欄位讀的就是這份內容。
|
|
816
|
+
|
|
817
|
+
Args:
|
|
818
|
+
content (str): 新的名片檔內容,會整份取代原本的內容。
|
|
819
|
+
|
|
820
|
+
Returns:
|
|
821
|
+
None
|
|
822
|
+
|
|
823
|
+
Raises:
|
|
824
|
+
RequireLogin: 需要登入。
|
|
825
|
+
|
|
826
|
+
範例::
|
|
827
|
+
|
|
828
|
+
import PyPtt
|
|
829
|
+
|
|
830
|
+
ptt_bot = PyPtt.API()
|
|
831
|
+
try:
|
|
832
|
+
# .. login ..
|
|
833
|
+
ptt_bot.set_signature_file(content='你好,我是 PyPtt')
|
|
834
|
+
# .. do something ..
|
|
835
|
+
finally:
|
|
836
|
+
ptt_bot.logout()
|
|
837
|
+
|
|
838
|
+
"""
|
|
839
|
+
|
|
840
|
+
_api_set_signature_file.set_signature_file(self, content)
|
|
841
|
+
|
|
809
842
|
def mark_post(self, mark_type: int, board: str, aid: Optional[str] = None, index: int = 0, search_type: int = 0,
|
|
810
843
|
search_condition: Optional[str] = None) -> None:
|
|
811
844
|
"""
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from . import _api_util
|
|
2
|
+
from . import check_value
|
|
3
|
+
from . import command
|
|
4
|
+
from . import connect_core
|
|
5
|
+
from . import exceptions
|
|
6
|
+
from . import i18n
|
|
7
|
+
from . import lib_util
|
|
8
|
+
from . import log
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def set_signature_file(api, content: str) -> None:
|
|
12
|
+
_api_util.one_thread(api)
|
|
13
|
+
|
|
14
|
+
if not api._is_login:
|
|
15
|
+
raise exceptions.RequireLogin(i18n.require_login)
|
|
16
|
+
|
|
17
|
+
check_value.check_type(content, str, 'content')
|
|
18
|
+
|
|
19
|
+
log.logger.info(i18n.set_signature_file)
|
|
20
|
+
|
|
21
|
+
cmd_list = []
|
|
22
|
+
cmd_list.append(command.go_main_menu)
|
|
23
|
+
cmd_list.append('U')
|
|
24
|
+
cmd_list.append(command.enter)
|
|
25
|
+
cmd_list.append('M')
|
|
26
|
+
cmd_list.append(command.enter)
|
|
27
|
+
cmd_list.append('Q')
|
|
28
|
+
cmd_list.append(command.enter)
|
|
29
|
+
cmd = ''.join(cmd_list)
|
|
30
|
+
|
|
31
|
+
target_list = [
|
|
32
|
+
# Existing signature file -> getans asks Delete/Edit/Cancel first.
|
|
33
|
+
# max_match=1: the echoed prompt text can linger on the next
|
|
34
|
+
# screen refresh while waiting for the editor to draw (same
|
|
35
|
+
# quirk documented for '確定要儲存檔案嗎' in _api_post.py); without
|
|
36
|
+
# it this would re-fire 'E' + Enter into the editor buffer.
|
|
37
|
+
connect_core.TargetUnit('名片 (D)刪除', response='E' + command.enter, max_match=1),
|
|
38
|
+
# Empty signature file skips the getans prompt and opens the
|
|
39
|
+
# editor directly.
|
|
40
|
+
connect_core.TargetUnit('編輯文章', break_detect=True),
|
|
41
|
+
]
|
|
42
|
+
index = api.connect_core.send(
|
|
43
|
+
cmd,
|
|
44
|
+
target_list,
|
|
45
|
+
screen_timeout=api.config.screen_long_timeout)
|
|
46
|
+
if index < 0:
|
|
47
|
+
ori_screen = api.connect_core.get_screen_queue()[-1]
|
|
48
|
+
raise exceptions.UnknownError(ori_screen)
|
|
49
|
+
|
|
50
|
+
content = lib_util.uniform_new_line(content)
|
|
51
|
+
|
|
52
|
+
cmd_list = []
|
|
53
|
+
# ponytail: unlike post's blank template, the card-file editor preloads
|
|
54
|
+
# the account's existing signature file, so it has to be cleared line by
|
|
55
|
+
# line before writing the new content. ctrl_y*60 is a "clear up to 60
|
|
56
|
+
# pre-loaded lines" ceiling -- bump it if a real card file ever runs
|
|
57
|
+
# longer than that.
|
|
58
|
+
cmd_list.append(command.ctrl_y * 60)
|
|
59
|
+
cmd_list.append(content)
|
|
60
|
+
cmd_list.append(command.ctrl_x)
|
|
61
|
+
cmd = ''.join(cmd_list)
|
|
62
|
+
|
|
63
|
+
target_list = [
|
|
64
|
+
connect_core.TargetUnit('確定要儲存檔案嗎', response='s' + command.enter, max_match=1),
|
|
65
|
+
connect_core.TargetUnit('名片更新完畢', break_detect=True),
|
|
66
|
+
]
|
|
67
|
+
index = api.connect_core.send(
|
|
68
|
+
cmd,
|
|
69
|
+
target_list,
|
|
70
|
+
screen_timeout=api.config.screen_long_timeout)
|
|
71
|
+
if index < 0:
|
|
72
|
+
ori_screen = api.connect_core.get_screen_queue()[-1]
|
|
73
|
+
raise exceptions.UnknownError(ori_screen)
|
|
74
|
+
|
|
75
|
+
# The leading space in go_main_menu dismisses the "請按任意鍵繼續" banner
|
|
76
|
+
# left by the save; the trailing left-arrows walk back out of the
|
|
77
|
+
# 個人設定/個人檔案 submenus to the main menu.
|
|
78
|
+
target_list = [
|
|
79
|
+
connect_core.TargetUnit('主功能表', break_detect=True),
|
|
80
|
+
]
|
|
81
|
+
api.connect_core.send(
|
|
82
|
+
command.go_main_menu,
|
|
83
|
+
target_list,
|
|
84
|
+
screen_timeout=api.config.screen_long_timeout)
|
|
85
|
+
|
|
86
|
+
log.logger.info(i18n.set_signature_file, '...', i18n.success)
|
|
@@ -106,6 +106,7 @@ string_data = {
|
|
|
106
106
|
"set_connect_host": "Set up the connect host",
|
|
107
107
|
"set_connect_mode": "Set up the connect mode",
|
|
108
108
|
"set_contact_mail_first": "Password can only be changed after setting the contact mailbox",
|
|
109
|
+
"set_signature_file": "Update signature file",
|
|
109
110
|
"set_up_lang_module": "Set up language module",
|
|
110
111
|
"spend_time": "Spend time",
|
|
111
112
|
"substandard_post": "Substandard post",
|
|
@@ -106,6 +106,7 @@ string_data = {
|
|
|
106
106
|
"set_connect_host": "設定連線主機",
|
|
107
107
|
"set_connect_mode": "設定連線模式",
|
|
108
108
|
"set_contact_mail_first": "請先設定聯絡信箱後才能修改密碼",
|
|
109
|
+
"set_signature_file": "更新名片檔",
|
|
109
110
|
"set_up_lang_module": "設定語言模組",
|
|
110
111
|
"spend_time": "花費時間",
|
|
111
112
|
"substandard_post": "不合規範文章",
|
|
@@ -30,6 +30,7 @@ PyPtt/_api_post.py
|
|
|
30
30
|
PyPtt/_api_reply_post.py
|
|
31
31
|
PyPtt/_api_search_user.py
|
|
32
32
|
PyPtt/_api_set_board_title.py
|
|
33
|
+
PyPtt/_api_set_signature_file.py
|
|
33
34
|
PyPtt/_api_util.py
|
|
34
35
|
PyPtt/api_server.py
|
|
35
36
|
PyPtt/check_value.py
|
|
@@ -92,4 +93,5 @@ tests/test_reply_post.py
|
|
|
92
93
|
tests/test_search_user.py
|
|
93
94
|
tests/test_service.py
|
|
94
95
|
tests/test_set_board_title.py
|
|
96
|
+
tests/test_set_signature_file.py
|
|
95
97
|
tests/test_vt100_parser.py
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Integration test for set_signature_file (the PTT "名片檔"/plan).
|
|
2
|
+
|
|
3
|
+
Self-restoring round-trip: capture the account's current signature file via
|
|
4
|
+
`get_user`, overwrite it with an identifiable marker, verify the marker shows
|
|
5
|
+
up on a fresh `get_user` read, then set it back to the original content so
|
|
6
|
+
the test doesn't leave a permanent change on the account.
|
|
7
|
+
"""
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
from PyPtt import UserField
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_set_signature_file_round_trip(ptt_bots):
|
|
14
|
+
for ptt_bot in ptt_bots:
|
|
15
|
+
original = ptt_bot.get_user(ptt_bot.ptt_id)[UserField.signature_file]
|
|
16
|
+
|
|
17
|
+
marker = f'PyPtt set_signature_file test {int(time.time())}'
|
|
18
|
+
try:
|
|
19
|
+
ptt_bot.set_signature_file(marker)
|
|
20
|
+
time.sleep(1)
|
|
21
|
+
|
|
22
|
+
updated = ptt_bot.get_user(ptt_bot.ptt_id)[UserField.signature_file]
|
|
23
|
+
assert marker in updated.strip()
|
|
24
|
+
finally:
|
|
25
|
+
# Restore -- must always run, even if the assertion above fails.
|
|
26
|
+
ptt_bot.set_signature_file(original)
|
|
27
|
+
time.sleep(1)
|
|
28
|
+
|
|
29
|
+
restored = ptt_bot.get_user(ptt_bot.ptt_id)[UserField.signature_file]
|
|
30
|
+
# Tolerate trailing whitespace/blank-line drift from the
|
|
31
|
+
# editor round-trip; compare on stripped content.
|
|
32
|
+
assert restored.strip() == original.strip()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|