PyPtt 2.1.3__tar.gz → 2.1.4__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.1.3 → pyptt-2.1.4}/PKG-INFO +1 -1
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/__init__.py +1 -1
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/connect_core.py +12 -4
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/screens.py +3 -1
- pyptt-2.1.4/PyPtt/ssl_config.py +24 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt.egg-info/PKG-INFO +1 -1
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_bucket.py +2 -1
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_del_post.py +25 -3
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_newest_index.py +12 -1
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_waterball.py +7 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_give_money.py +5 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_mark_post.py +3 -2
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_service.py +7 -1
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_set_board_title.py +2 -1
- pyptt-2.1.3/PyPtt/ssl_config.py +0 -24
- {pyptt-2.1.3 → pyptt-2.1.4}/LICENSE +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/PTT.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_bucket.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_call_status.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_change_pw.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_comment.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_del_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_board_info.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_board_list.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_bottom_post_list.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_favourite_board.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_newest_index.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_post_index.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_post_list.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_time.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_user.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_get_waterball.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_give_money.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_has_new_mail.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_loginout.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_mail.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_mark_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_reply_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_search_user.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_set_board_title.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/_api_util.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/api_server.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/check_value.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/command.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/config.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/data_type.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/exceptions.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/i18n.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/lang_en_US.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/lang_zh_TW.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/lib_util.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/log.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt/service.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt.egg-info/SOURCES.txt +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt.egg-info/dependency_links.txt +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt.egg-info/requires.txt +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/PyPtt.egg-info/top_level.txt +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/README.md +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/pyproject.toml +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/setup.cfg +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/setup.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_change_pw.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_comment.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_exceptions.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_fast_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_board_info.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_board_list.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_bottom_post_list.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_content_formula.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_favourite_boards.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_mail.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_post_list.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_post_list_parser.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_post_parser.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_time.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_get_user.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_i18n.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_init.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_logger.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_mail_send_and_del.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_parse_query_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_pyte_parity.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_reply_post.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_search_user.py +0 -0
- {pyptt-2.1.3 → pyptt-2.1.4}/tests/test_vt100_parser.py +0 -0
|
@@ -196,8 +196,12 @@ class API(object):
|
|
|
196
196
|
websocket_host = 'wss://ws.ptt2.cc/bbs/'
|
|
197
197
|
websocket_origin = 'https://term.ptt2.cc'
|
|
198
198
|
elif self.config.host == data_type.HOST.LOCALHOST:
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
# ponytail: local pttbbs docker image (bbsdocker/imageptt) serves plain ws
|
|
200
|
+
# (no TLS) on 48763; config.port defaults to 23 (telnet default) so treat
|
|
201
|
+
# that as "not set" and fall back to imageptt's default port
|
|
202
|
+
port = self.config.port if self.config.port != 23 else 48763
|
|
203
|
+
websocket_host = f'ws://localhost:{port}/bbs'
|
|
204
|
+
websocket_origin = 'http://localhost'
|
|
201
205
|
else:
|
|
202
206
|
websocket_host = f'wss://{self.config.host}'
|
|
203
207
|
websocket_origin = 'https://term.ptt.cc'
|
|
@@ -209,11 +213,15 @@ class API(object):
|
|
|
209
213
|
try:
|
|
210
214
|
log.logger.debug('USER_AGENT',
|
|
211
215
|
websockets.http11.USER_AGENT if use_http11 else websockets.http.USER_AGENT)
|
|
216
|
+
# ponytail: ws:// (local docker target) can't take an ssl context —
|
|
217
|
+
# websockets errors out if you pass one on a non-wss URI
|
|
218
|
+
connect_kwargs = {'origin': websocket_origin}
|
|
219
|
+
if websocket_host.startswith('wss://'):
|
|
220
|
+
connect_kwargs['ssl'] = self._ssl_context
|
|
212
221
|
self._core = loop.run_until_complete(
|
|
213
222
|
websockets.connect(
|
|
214
223
|
websocket_host,
|
|
215
|
-
|
|
216
|
-
ssl=self._ssl_context))
|
|
224
|
+
**connect_kwargs))
|
|
217
225
|
# Respond to PTT's IAC DO NAWS (ff fd 1f) and announce terminal size.
|
|
218
226
|
# PTT honours any height >= 24; larger values reduce get_content iterations.
|
|
219
227
|
# PTT's hard cap is 100 rows regardless of what we send.
|
|
@@ -199,7 +199,9 @@ class Target:
|
|
|
199
199
|
content_end_list = [
|
|
200
200
|
'--\n※ 發信站: 批踢踢實業坊',
|
|
201
201
|
'--\n※ 發信站: 批踢踢兔(ptt2.cc)',
|
|
202
|
-
'--\n※ 發信站: 新批踢踢(ptt2.twbbs.org.tw)'
|
|
202
|
+
'--\n※ 發信站: 新批踢踢(ptt2.twbbs.org.tw)',
|
|
203
|
+
# bbsdocker/imageptt (HOST.LOCALHOST test container) site name.
|
|
204
|
+
'--\n※ 發信站: 批踢踢 docker(pttdocker.test)'
|
|
203
205
|
]
|
|
204
206
|
|
|
205
207
|
OnlineUser = [
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
key = """-----BEGIN EC PARAMETERS-----
|
|
2
|
+
BggqhkjOPQMBBw==
|
|
3
|
+
-----END EC PARAMETERS-----
|
|
4
|
+
-----BEGIN EC PRIVATE KEY-----
|
|
5
|
+
MHcCAQEEIPSUMd0VM3Lz9oHqzRjDOoA7mMSwkff1CvCmOhswqdeToAoGCCqGSM49
|
|
6
|
+
AwEHoUQDQgAEFL8NgpDyAYc1AfvrY4QeOOF5bEaj3fQyrfF+SQhRzgqnKFPxCVVs
|
|
7
|
+
qPE3yCC7L/2VweGjoPMg1YPOsSTsiliqlg==
|
|
8
|
+
-----END EC PRIVATE KEY-----
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
cert = """-----BEGIN CERTIFICATE-----
|
|
12
|
+
MIIB6jCCAY8CFFnMpZwQZ949yt925TXsbCqq9/+SMAoGCCqGSM49BAMCMHcxCzAJ
|
|
13
|
+
BgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UE
|
|
14
|
+
CgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25hbCBVbml0MRQw
|
|
15
|
+
EgYDVQQDDAtDb21tb24gTmFtZTAeFw0yNjA3MTMxNTE4MDhaFw0zNjA3MTAxNTE4
|
|
16
|
+
MDhaMHcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0
|
|
17
|
+
eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25h
|
|
18
|
+
bCBVbml0MRQwEgYDVQQDDAtDb21tb24gTmFtZTBZMBMGByqGSM49AgEGCCqGSM49
|
|
19
|
+
AwEHA0IABBS/DYKQ8gGHNQH762OEHjjheWxGo930Mq3xfkkIUc4KpyhT8QlVbKjx
|
|
20
|
+
N8gguy/9lcHho6DzINWDzrEk7IpYqpYwCgYIKoZIzj0EAwIDSQAwRgIhAJaKKQ+t
|
|
21
|
+
oEPH2j3xs3Rg3F3IR/8EdlzdD+mFPoXtjl9dAiEAhvHMefijy34Ya268zOGArdNz
|
|
22
|
+
5msfSDH5QT27scqencw=
|
|
23
|
+
-----END CERTIFICATE-----
|
|
24
|
+
"""
|
|
@@ -17,6 +17,7 @@ import pytest
|
|
|
17
17
|
|
|
18
18
|
import PyPtt
|
|
19
19
|
from tests import config
|
|
20
|
+
from tests import util
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def test_bucket_nonexistent_user_raises(ptt_bots):
|
|
@@ -38,7 +39,7 @@ def test_bucket_on_moderated_board(ptt_bots):
|
|
|
38
39
|
if not config.MOD_BOARD:
|
|
39
40
|
pytest.skip('MOD_BOARD env var not set')
|
|
40
41
|
for ptt_bot in ptt_bots:
|
|
41
|
-
if ptt_bot
|
|
42
|
+
if not util.is_primary_host(ptt_bot, ptt_bots):
|
|
42
43
|
continue
|
|
43
44
|
try:
|
|
44
45
|
ptt_bot.bucket(
|
|
@@ -5,6 +5,7 @@ import pytest
|
|
|
5
5
|
|
|
6
6
|
import PyPtt
|
|
7
7
|
from tests import config
|
|
8
|
+
from tests import util
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def test_del_own_post(ptt_bots):
|
|
@@ -25,6 +26,8 @@ def test_del_own_post(ptt_bots):
|
|
|
25
26
|
|
|
26
27
|
# 2. Verify we found our post
|
|
27
28
|
for i in range(5):
|
|
29
|
+
if newest_index - i <= 0:
|
|
30
|
+
continue
|
|
28
31
|
post_data = ptt_bot.get_post('Test', index=newest_index - i)
|
|
29
32
|
|
|
30
33
|
if post_data['author'].startswith(ptt_bot.ptt_id):
|
|
@@ -36,13 +39,24 @@ def test_del_own_post(ptt_bots):
|
|
|
36
39
|
# 3. Delete the post
|
|
37
40
|
|
|
38
41
|
for i in range(5): # Retry up to 3 times in case of transient issues
|
|
42
|
+
if newest_index - i <= 0:
|
|
43
|
+
continue
|
|
39
44
|
try:
|
|
40
45
|
ptt_bot.del_post(board='Test', index=newest_index - i)
|
|
41
46
|
except PyPtt.exceptions.NoPermission:
|
|
42
47
|
pass
|
|
43
48
|
|
|
44
49
|
for i in range(5):
|
|
45
|
-
|
|
50
|
+
if newest_index - i <= 0:
|
|
51
|
+
continue
|
|
52
|
+
try:
|
|
53
|
+
deleted_post_data = ptt_bot.get_post('Test', index=newest_index - i)
|
|
54
|
+
except PyPtt.exceptions.ParameterError:
|
|
55
|
+
# On a small local board, deleting every remaining post can
|
|
56
|
+
# shrink the board's live index range out from under this
|
|
57
|
+
# stale `newest_index`; an out-of-range index unambiguously
|
|
58
|
+
# means the post is gone, which is what this loop checks for.
|
|
59
|
+
continue
|
|
46
60
|
|
|
47
61
|
print(json.dumps(deleted_post_data, ensure_ascii=False, indent=2))
|
|
48
62
|
|
|
@@ -72,6 +86,8 @@ def test_del_other_post_permission_error(ptt_bots):
|
|
|
72
86
|
target_index = -1
|
|
73
87
|
for i in range(10): # Check the last 10 posts
|
|
74
88
|
index_to_check = newest_index - i
|
|
89
|
+
if index_to_check <= 0:
|
|
90
|
+
continue
|
|
75
91
|
try:
|
|
76
92
|
post = ptt_bot.get_post(board, index=index_to_check, query=True)
|
|
77
93
|
if post[PyPtt.PostField.post_status] == PyPtt.PostStatus.EXISTS and not post['author'].startswith(
|
|
@@ -101,6 +117,8 @@ def test_del_own_post_with_reason_raises(ptt_bots):
|
|
|
101
117
|
newest_index = ptt_bot.get_newest_index(PyPtt.NewIndex.BOARD, board='Test')
|
|
102
118
|
index = -1
|
|
103
119
|
for i in range(5):
|
|
120
|
+
if newest_index - i <= 0:
|
|
121
|
+
continue
|
|
104
122
|
post_data = ptt_bot.get_post('Test', index=newest_index - i)
|
|
105
123
|
if post_data['author'].startswith(ptt_bot.ptt_id) and \
|
|
106
124
|
post_data['title'] == f"[測試] {post_title}":
|
|
@@ -122,8 +140,12 @@ def test_del_other_post_with_reason_as_moderator(ptt_bots):
|
|
|
122
140
|
if not config.MOD_BOARD:
|
|
123
141
|
pytest.skip('MOD_BOARD env var not set')
|
|
124
142
|
for ptt_bot in ptt_bots:
|
|
125
|
-
if ptt_bot
|
|
126
|
-
continue # MOD_BOARD is
|
|
143
|
+
if not util.is_primary_host(ptt_bot, ptt_bots):
|
|
144
|
+
continue # MOD_BOARD is moderated by the primary bot
|
|
145
|
+
|
|
146
|
+
if ptt_bot.host == PyPtt.HOST.LOCALHOST:
|
|
147
|
+
pytest.skip('local imageptt hard-deletes and reindexes moderator '
|
|
148
|
+
'posts, leaving no DELETED_BY_MODERATOR tombstone to read back')
|
|
127
149
|
|
|
128
150
|
board = config.MOD_BOARD
|
|
129
151
|
newest_index = ptt_bot.get_newest_index(PyPtt.NewIndex.BOARD, board=board)
|
|
@@ -20,6 +20,15 @@ PTT2_BOARD_CASES = [
|
|
|
20
20
|
('PttSuggest', PyPtt.SearchType.KEYWORD, '[問題]'),
|
|
21
21
|
]
|
|
22
22
|
|
|
23
|
+
# The PTT1/PTT2 cases above search real, host-specific historical posts and
|
|
24
|
+
# boards that don't exist on a local imageptt container. `Python` is seeded
|
|
25
|
+
# with at least one post by scripts/bootstrap_local_pttbbs.py and — unlike
|
|
26
|
+
# `Test` — no other test in the suite deletes from it, so its post count
|
|
27
|
+
# only ever grows across a full-suite run.
|
|
28
|
+
LOCALHOST_BOARD_CASES = [
|
|
29
|
+
('Python', None, None),
|
|
30
|
+
]
|
|
31
|
+
|
|
23
32
|
def test_get_mail_index(ptt_bots):
|
|
24
33
|
"""Tests getting the newest mail index."""
|
|
25
34
|
for ptt_bot in ptt_bots:
|
|
@@ -30,7 +39,9 @@ def test_get_mail_index(ptt_bots):
|
|
|
30
39
|
def test_get_board_index(ptt_bots):
|
|
31
40
|
"""Tests getting the newest board index on PTT2 with various search parameters."""
|
|
32
41
|
for ptt_bot in ptt_bots:
|
|
33
|
-
if ptt_bot.config.host == PyPtt.HOST.
|
|
42
|
+
if ptt_bot.config.host == PyPtt.HOST.LOCALHOST:
|
|
43
|
+
test_params = LOCALHOST_BOARD_CASES
|
|
44
|
+
elif ptt_bot.config.host == PyPtt.HOST.PTT1:
|
|
34
45
|
test_params = PTT1_BOARD_CASES
|
|
35
46
|
else:
|
|
36
47
|
test_params = PTT2_BOARD_CASES
|
|
@@ -7,9 +7,16 @@ try:
|
|
|
7
7
|
except KeyError:
|
|
8
8
|
import config
|
|
9
9
|
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
# ponytail: PTT_HOST=LOCALHOST points at a local imageptt docker container
|
|
13
|
+
# instead of the real PTT1 host; unset keeps the status quo.
|
|
14
|
+
_use_localhost = os.environ.get('PTT_HOST') == 'LOCALHOST'
|
|
15
|
+
|
|
10
16
|
|
|
11
17
|
def test_get_waterball():
|
|
12
18
|
ptt1_bot = PyPtt.API(
|
|
19
|
+
host=PyPtt.HOST.LOCALHOST if _use_localhost else PyPtt.HOST.PTT1,
|
|
13
20
|
)
|
|
14
21
|
ptt1_bot.login(ptt_id=config.PTT1_ID, ptt_pw=config.PTT1_PW, kick_other_session=True)
|
|
15
22
|
|
|
@@ -12,6 +12,11 @@ def test_give_money(ptt_bots):
|
|
|
12
12
|
# PTT2 test host does not support giving money.
|
|
13
13
|
if ptt_bot.host == PyPtt.HOST.PTT2:
|
|
14
14
|
continue
|
|
15
|
+
# Can't give money to yourself — under LOCALHOST both bots share the
|
|
16
|
+
# same .host value, so the PTT2 skip above doesn't disambiguate them,
|
|
17
|
+
# and TEST_USER may legitimately be the PTT2 account's own ptt_id.
|
|
18
|
+
if ptt_bot.ptt_id.lower() == recipient_id.lower():
|
|
19
|
+
continue
|
|
15
20
|
|
|
16
21
|
try:
|
|
17
22
|
# This call should not raise an exception on success
|
|
@@ -13,6 +13,7 @@ import pytest
|
|
|
13
13
|
import PyPtt
|
|
14
14
|
from PyPtt import PostField, NewIndex
|
|
15
15
|
from tests import config
|
|
16
|
+
from tests import util
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
def _post_and_get_aid(ptt_bot, board: str) -> str:
|
|
@@ -39,8 +40,8 @@ def test_mark_post_on_moderated_board(ptt_bots):
|
|
|
39
40
|
if not config.MOD_BOARD:
|
|
40
41
|
pytest.skip('MOD_BOARD env var not set')
|
|
41
42
|
for ptt_bot in ptt_bots:
|
|
42
|
-
if ptt_bot
|
|
43
|
-
continue # MOD_BOARD is
|
|
43
|
+
if not util.is_primary_host(ptt_bot, ptt_bots):
|
|
44
|
+
continue # MOD_BOARD is moderated by the primary bot
|
|
44
45
|
aid = _post_and_get_aid(ptt_bot, board=config.MOD_BOARD)
|
|
45
46
|
try:
|
|
46
47
|
ptt_bot.mark_post(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
2
4
|
import PyPtt
|
|
3
5
|
import threading
|
|
@@ -5,6 +7,10 @@ import time
|
|
|
5
7
|
from PyPtt import Service, PostField
|
|
6
8
|
from tests import config # Assuming config.py has PTT1_ID and PTT1_PW
|
|
7
9
|
|
|
10
|
+
# ponytail: PTT_HOST=LOCALHOST points at a local imageptt docker container
|
|
11
|
+
# instead of the real PTT1 host; unset keeps the status quo.
|
|
12
|
+
_use_localhost = os.environ.get('PTT_HOST') == 'LOCALHOST'
|
|
13
|
+
|
|
8
14
|
class TestCallInterval:
|
|
9
15
|
"""Tests for call_interval feature (no network required)."""
|
|
10
16
|
|
|
@@ -56,7 +62,7 @@ class TestCallInterval:
|
|
|
56
62
|
def service_instance():
|
|
57
63
|
import time
|
|
58
64
|
|
|
59
|
-
pyptt_init_config = {}
|
|
65
|
+
pyptt_init_config = {'host': PyPtt.HOST.LOCALHOST} if _use_localhost else {}
|
|
60
66
|
service = Service(pyptt_init_config)
|
|
61
67
|
|
|
62
68
|
max_retries = 3
|
|
@@ -16,6 +16,7 @@ import pytest
|
|
|
16
16
|
|
|
17
17
|
import PyPtt
|
|
18
18
|
from tests import config
|
|
19
|
+
from tests import util
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def test_a_set_board_title_without_moderator_perm_raises(ptt_bots):
|
|
@@ -36,7 +37,7 @@ def test_b_set_board_title_on_moderated_board(ptt_bots):
|
|
|
36
37
|
if not config.MOD_BOARD:
|
|
37
38
|
pytest.skip('MOD_BOARD env var not set')
|
|
38
39
|
for ptt_bot in ptt_bots:
|
|
39
|
-
if ptt_bot
|
|
40
|
+
if not util.is_primary_host(ptt_bot, ptt_bots):
|
|
40
41
|
continue
|
|
41
42
|
info = ptt_bot.get_board_info(board=config.MOD_BOARD)
|
|
42
43
|
original = info[PyPtt.BoardField.mandarin_des]
|
pyptt-2.1.3/PyPtt/ssl_config.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
key = """-----BEGIN EC PARAMETERS-----
|
|
2
|
-
BggqhkjOPQMBBw==
|
|
3
|
-
-----END EC PARAMETERS-----
|
|
4
|
-
-----BEGIN EC PRIVATE KEY-----
|
|
5
|
-
MHcCAQEEIEkOJyMNiLY15Dbj6KQAQzcL8VCnyWHTZRAtIku05VDZoAoGCCqGSM49
|
|
6
|
-
AwEHoUQDQgAEKUSVL5IptOLhRvvjbwASpbMm2u9g5bB+JzwZFipu7YcP/M3O/hdn
|
|
7
|
-
itOTx/TQ1WUZzOO1K8VVP+PiJ848Gf7oXQ==
|
|
8
|
-
-----END EC PRIVATE KEY-----
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
cert = """-----BEGIN CERTIFICATE-----
|
|
12
|
-
MIIB6DCCAY8CFBQB2jo2W/VcD/OwELD8q619nPFLMAoGCCqGSM49BAMCMHcxCzAJ
|
|
13
|
-
BgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UE
|
|
14
|
-
CgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25hbCBVbml0MRQw
|
|
15
|
-
EgYDVQQDDAtDb21tb24gTmFtZTAeFw0yNjA2MjkxMzI5MjNaFw0zNjA2MjYxMzI5
|
|
16
|
-
MjNaMHcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0
|
|
17
|
-
eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25h
|
|
18
|
-
bCBVbml0MRQwEgYDVQQDDAtDb21tb24gTmFtZTBZMBMGByqGSM49AgEGCCqGSM49
|
|
19
|
-
AwEHA0IABClElS+SKbTi4Ub7428AEqWzJtrvYOWwfic8GRYqbu2HD/zNzv4XZ4rT
|
|
20
|
-
k8f00NVlGczjtSvFVT/j4ifOPBn+6F0wCgYIKoZIzj0EAwIDRwAwRAIgXp4Ylzan
|
|
21
|
-
xWWkNTM2MrkPDIy06zA6vLWkKaXNaTRbc+8CICnfggxFK7IrkX5Z7ZOstjCaO+kd
|
|
22
|
-
/xwJcAEv99IpTAr/
|
|
23
|
-
-----END CERTIFICATE-----
|
|
24
|
-
"""
|
|
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
|