PyPtt 1.2.19__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {pyptt-1.2.19 → pyptt-1.3.0}/PKG-INFO +1 -1
  2. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/PTT.py +31 -0
  3. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/__init__.py +2 -2
  4. pyptt-1.3.0/PyPtt/_api_get_post_list.py +100 -0
  5. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_util.py +1 -1
  6. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/check_value.py +12 -6
  7. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/command.py +3 -0
  8. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/lang_en_US.py +2 -1
  9. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/lang_zh_TW.py +2 -1
  10. pyptt-1.3.0/PyPtt/ssl_config.py +24 -0
  11. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt.egg-info/PKG-INFO +1 -1
  12. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt.egg-info/SOURCES.txt +1 -0
  13. pyptt-1.2.19/PyPtt/ssl_config.py +0 -24
  14. {pyptt-1.2.19 → pyptt-1.3.0}/LICENSE +0 -0
  15. {pyptt-1.2.19 → pyptt-1.3.0}/MANIFEST.in +0 -0
  16. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_bucket.py +0 -0
  17. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_call_status.py +0 -0
  18. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_change_pw.py +0 -0
  19. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_comment.py +0 -0
  20. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_del_post.py +0 -0
  21. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_board_info.py +0 -0
  22. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_board_list.py +0 -0
  23. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_bottom_post_list.py +0 -0
  24. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_favourite_board.py +0 -0
  25. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_newest_index.py +0 -0
  26. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_post.py +0 -0
  27. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_post_index.py +0 -0
  28. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_time.py +0 -0
  29. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_get_user.py +0 -0
  30. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_give_money.py +0 -0
  31. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_has_new_mail.py +0 -0
  32. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_loginout.py +0 -0
  33. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_mail.py +0 -0
  34. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_mark_post.py +0 -0
  35. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_post.py +0 -0
  36. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_reply_post.py +0 -0
  37. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_search_user.py +0 -0
  38. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/_api_set_board_title.py +0 -0
  39. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/config.py +0 -0
  40. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/connect_core.py +0 -0
  41. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/data_type.py +0 -0
  42. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/exceptions.py +0 -0
  43. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/i18n.py +0 -0
  44. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/lib_util.py +0 -0
  45. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/log.py +0 -0
  46. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/screens.py +0 -0
  47. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt/service.py +0 -0
  48. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt.egg-info/dependency_links.txt +0 -0
  49. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt.egg-info/requires.txt +0 -0
  50. {pyptt-1.2.19 → pyptt-1.3.0}/PyPtt.egg-info/top_level.txt +0 -0
  51. {pyptt-1.2.19 → pyptt-1.3.0}/README.md +0 -0
  52. {pyptt-1.2.19 → pyptt-1.3.0}/setup.cfg +0 -0
  53. {pyptt-1.2.19 → pyptt-1.3.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPtt
3
- Version: 1.2.19
3
+ Version: 1.3.0
4
4
  Summary: PyPtt
5
5
  Home-page: https://pyptt.cc/
6
6
  Author: CodingMan
@@ -15,6 +15,7 @@ from . import _api_get_bottom_post_list
15
15
  from . import _api_get_favourite_board
16
16
  from . import _api_get_newest_index
17
17
  from . import _api_get_post
18
+ from . import _api_get_post_list
18
19
  from . import _api_get_time
19
20
  from . import _api_get_user
20
21
  from . import _api_give_money
@@ -1055,6 +1056,36 @@ class API:
1055
1056
 
1056
1057
  _api_del_post.del_post(self, board, aid, index)
1057
1058
 
1059
+ def get_post_list(self, board: str, limit: int = 20, offset: int = 0) -> list[dict]:
1060
+ """
1061
+ 取得文章列表。
1062
+
1063
+ Args:
1064
+ board (str): 看板名稱。
1065
+ limit (int): 取得文章數量,預設為 20。
1066
+ offset (int): 偏移量,預設為 0。
1067
+ Returns:
1068
+ list[dict],文章列表,詳見 :ref:`post-field`。
1069
+
1070
+ Raises:
1071
+ RequireLogin: 需要登入。
1072
+ NoSuchBoard: 看板不存在。
1073
+
1074
+ 範例::
1075
+
1076
+ import PyPtt
1077
+
1078
+ ptt_bot = PyPtt.API()
1079
+ try:
1080
+ # .. login ..
1081
+ post_list = ptt_bot.get_post_list(board='Python', limit=10, offset=0)
1082
+ # .. do something ..
1083
+ finally:
1084
+ ptt_bot.logout()
1085
+ """
1086
+
1087
+ return _api_get_post_list.get_post_list(self, board, limit, offset)
1088
+
1058
1089
  def fast_post_step0(self, board: str, title: str, content: str, post_type: int) -> None:
1059
1090
  _api_post.fast_post_step0(self, board, title, content, post_type)
1060
1091
 
@@ -1,4 +1,4 @@
1
- __version__ = '1.2.19'
1
+ __version__ = '1.3.0'
2
2
 
3
3
  from .PTT import API
4
4
  from .data_type import *
@@ -8,4 +8,4 @@ from .service import Service
8
8
 
9
9
  LOG_LEVEL = LogLevel
10
10
 
11
- _main_version = '1.2'
11
+ _main_version = '1.3'
@@ -0,0 +1,100 @@
1
+ from typing import Dict, List
2
+
3
+ from . import _api_util
4
+ from . import check_value
5
+ from . import command
6
+ from . import connect_core
7
+ from . import data_type
8
+ from . import exceptions
9
+ from . import i18n
10
+ from . import log
11
+ from . import screens
12
+
13
+
14
+ def get_post_list(api, board: str, limit: int = 20, offset: int = 0) -> List[Dict]:
15
+ _api_util.one_thread(api)
16
+
17
+ if not api._is_login:
18
+ raise exceptions.RequireLogin(i18n.require_login)
19
+
20
+ check_value.check_type(board, str, 'board')
21
+ if limit is not None:
22
+ check_value.check_type(limit, int, 'limit')
23
+ if offset is not None:
24
+ check_value.check_type(offset, int, 'offset')
25
+
26
+ max_index = api.get_newest_index(data_type.NewIndex.BOARD, board=board)
27
+
28
+ check_value.check_range(limit, min_value=1, max_value=max_index, name='limit')
29
+ check_value.check_range(offset, min_value=0, max_value=max_index - 1, name='offset')
30
+
31
+ start_index = max_index - limit - offset + 1
32
+ end_index = start_index + limit - 1
33
+
34
+ # the first page shows 10 posts, each next page shows 20 posts
35
+ if limit <= 10:
36
+ max_round = 1
37
+ else:
38
+ # 1 is for the first page, +1 is for rounding up
39
+ # so +2
40
+ max_round = (limit - 10) // 20 + 2
41
+
42
+ cmd_list = []
43
+
44
+ cmd_list.append(str(max(1, start_index - 100)))
45
+ cmd_list.append(command.enter)
46
+ cmd_list.append(str(start_index))
47
+ cmd_list.append(command.enter)
48
+
49
+ cmd = ''.join(cmd_list)
50
+
51
+ target_list = [
52
+ connect_core.TargetUnit(screens.Target.InBoard, log_level=log.DEBUG, break_detect=True)
53
+ ]
54
+
55
+ post_list = []
56
+
57
+ for _ in range(max_round):
58
+
59
+ index = api.connect_core.send(cmd, target_list)
60
+ cmd = command.page_down
61
+ last_screen = api.connect_core.get_screen_queue()[-1]
62
+
63
+ is_parse_area = False
64
+
65
+ for line in last_screen.splitlines()[3:-1]:
66
+
67
+ if not line.startswith(api.cursor) and not is_parse_area:
68
+ continue
69
+ is_parse_area = True
70
+
71
+ if line.strip().startswith(api.cursor):
72
+ # replace the first cursor in the line
73
+ line = line.replace(api.cursor, ' ' * len(api.cursor.encode('big5uao')), 1)
74
+
75
+ if api.cursor == data_type.Cursor.NEW:
76
+ # add one space in the beginning to align the old cursor line
77
+ line = f' {line}'
78
+
79
+ cur_index = int(line[:8].strip())
80
+ status = line[8:10].strip()
81
+ comment = line[10:12].strip()
82
+ list_date = line[12:17].strip()
83
+ author = line[18:31].strip()
84
+ title = line[31:]
85
+
86
+ cur_post = {
87
+ data_type.PostField.board: board,
88
+ data_type.PostField.index: cur_index,
89
+ data_type.PostField.list_date: list_date,
90
+ data_type.PostField.author: author,
91
+ data_type.PostField.title: title,
92
+ data_type.PostField.push_number: comment
93
+ }
94
+
95
+ post_list.append(cur_post)
96
+
97
+ if cur_index >= end_index:
98
+ return post_list
99
+
100
+ raise exceptions.UnknownError(i18n.unknown_error)
@@ -94,7 +94,7 @@ def get_content(api, post_mode: bool = True):
94
94
  # 這裡是 PyPtt 最黑暗最墮落的地方,所有你所知的程式碼守則,在這裡都不適用
95
95
  # 每除完一次錯誤,我會陷入嚴重的創傷後壓力症候群,而我的腦袋會自動選擇遺忘這裡所有的一切
96
96
  # 以確保下一個週一,我可以正常上班
97
- # but it works!
97
+ # but it works!!!
98
98
 
99
99
  # print(LastScreen)
100
100
  # print(f'last_read_line_a_temp [{last_read_line_a_temp}]')
@@ -15,14 +15,20 @@ def check_type(value, value_type, name) -> None:
15
15
  raise TypeError(f'[PyPtt] {name} {i18n.must_be} {value_type}, but got {value}')
16
16
 
17
17
 
18
- def check_range(value, min_value, max_value, name) -> None:
18
+ def check_range(value, min_value: int = None, max_value: int = None, name: str = None) -> None:
19
19
  check_type(value, int, name)
20
- check_type(min_value, int, 'min_value')
21
- check_type(max_value, int, 'max_value')
22
20
 
23
- if min_value <= value <= max_value:
24
- return
25
- raise exceptions.ParameterError(f'{name} {value} {i18n.must_between} {min_value} ~ {max_value}')
21
+ if min_value is not None:
22
+ check_type(min_value, int, 'min_value')
23
+
24
+ if value < min_value:
25
+ raise exceptions.ParameterError(f'{name} {value} {i18n.must_between} {min_value} ~ {max_value}')
26
+
27
+ if max_value is not None:
28
+ check_type(max_value, int, 'max_value')
29
+
30
+ if value > max_value:
31
+ raise exceptions.ParameterError(f'{name} {value} {i18n.must_between} {min_value} ~ {max_value}')
26
32
 
27
33
 
28
34
  def check_index(name, index, max_value=None) -> None:
@@ -26,3 +26,6 @@ go_main_menu_type_q = 'q' * 5
26
26
  refresh = ctrl_l
27
27
  control_code = ctrl_u + star
28
28
  backspace = ctrl_h
29
+
30
+ page_up = 'P'
31
+ page_down = 'N'
@@ -115,5 +115,6 @@ string_data = {
115
115
  "user_offline": "User offline",
116
116
  "wait_for_no_fast_comment": "Because no fast comment, wait 5 sec",
117
117
  "welcome": "PyPtt v _target0_ developed by CodingMan",
118
- "wrong_id_pw": "Wrong id or pw"
118
+ "wrong_id_pw": "Wrong id or pw",
119
+ "unknown_error": "Unknown error",
119
120
  }
@@ -115,5 +115,6 @@ string_data = {
115
115
  "user_offline": "使用者離線",
116
116
  "wait_for_no_fast_comment": "因禁止快速連續推文,所以等待五秒",
117
117
  "welcome": "PyPtt v _target0_ 由 CodingMan 開發",
118
- "wrong_id_pw": "帳號密碼錯誤"
118
+ "wrong_id_pw": "帳號密碼錯誤",
119
+ "unknown_error": "未知錯誤",
119
120
  }
@@ -0,0 +1,24 @@
1
+ key = """-----BEGIN EC PARAMETERS-----
2
+ BggqhkjOPQMBBw==
3
+ -----END EC PARAMETERS-----
4
+ -----BEGIN EC PRIVATE KEY-----
5
+ MHcCAQEEIKw/h9H04KLxJfnIkNO3wM2+JjX8VOiAAkv2vK2P4H1HoAoGCCqGSM49
6
+ AwEHoUQDQgAEnRlm+zkKvXUfHbay5w4QYc4GO5X/RVA+b7iPAcJdjapPnXBgdWxd
7
+ nqIJiHX/7a5OIcgZ5rjs8zUtc0UlYe7eEA==
8
+ -----END EC PRIVATE KEY-----
9
+ """
10
+
11
+ cert = """-----BEGIN CERTIFICATE-----
12
+ MIIB6jCCAY8CFCNOe3ddTd3VNwEtsYwbTsN8qW5oMAoGCCqGSM49BAMCMHcxCzAJ
13
+ BgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UE
14
+ CgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25hbCBVbml0MRQw
15
+ EgYDVQQDDAtDb21tb24gTmFtZTAeFw0yNTA5MDcwNzMwMTlaFw0zNTA5MDUwNzMw
16
+ MTlaMHcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0
17
+ eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25h
18
+ bCBVbml0MRQwEgYDVQQDDAtDb21tb24gTmFtZTBZMBMGByqGSM49AgEGCCqGSM49
19
+ AwEHA0IABJ0ZZvs5Cr11Hx22sucOEGHOBjuV/0VQPm+4jwHCXY2qT51wYHVsXZ6i
20
+ CYh1/+2uTiHIGea47PM1LXNFJWHu3hAwCgYIKoZIzj0EAwIDSQAwRgIhAPoAa/vC
21
+ T5pmcdQRjItJuMvCdbX2AZIE58LZ2azm0rNkAiEA94lVjUIEcC6cZIR3b0ZhtEEc
22
+ fhFBVrfHxjt/rmXT3os=
23
+ -----END CERTIFICATE-----
24
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPtt
3
- Version: 1.2.19
3
+ Version: 1.3.0
4
4
  Summary: PyPtt
5
5
  Home-page: https://pyptt.cc/
6
6
  Author: CodingMan
@@ -16,6 +16,7 @@ PyPtt/_api_get_favourite_board.py
16
16
  PyPtt/_api_get_newest_index.py
17
17
  PyPtt/_api_get_post.py
18
18
  PyPtt/_api_get_post_index.py
19
+ PyPtt/_api_get_post_list.py
19
20
  PyPtt/_api_get_time.py
20
21
  PyPtt/_api_get_user.py
21
22
  PyPtt/_api_give_money.py
@@ -1,24 +0,0 @@
1
- key = """-----BEGIN EC PARAMETERS-----
2
- BggqhkjOPQMBBw==
3
- -----END EC PARAMETERS-----
4
- -----BEGIN EC PRIVATE KEY-----
5
- MHcCAQEEIG4BOpPiAtfiRgc2DydA/wkdxOGaxwH+exd4MXa4Cja8oAoGCCqGSM49
6
- AwEHoUQDQgAEDS/OWw/BDHH2l2pZO6LPmWqNUKmuPNSJ7xbtVxsIpuJwNxntrch6
7
- qbU2VrVjYuzRAjQvjff9rgC9kJLGi+Z2OQ==
8
- -----END EC PRIVATE KEY-----
9
- """
10
-
11
- cert = """-----BEGIN CERTIFICATE-----
12
- MIIB6DCCAY8CFAnIVb8H7lNPfebaSJJTQ0vn9OfhMAoGCCqGSM49BAMCMHcxCzAJ
13
- BgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UE
14
- CgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25hbCBVbml0MRQw
15
- EgYDVQQDDAtDb21tb24gTmFtZTAeFw0yNTA3MTAwNjM3MDNaFw0zNTA3MDgwNjM3
16
- MDNaMHcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0
17
- eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25h
18
- bCBVbml0MRQwEgYDVQQDDAtDb21tb24gTmFtZTBZMBMGByqGSM49AgEGCCqGSM49
19
- AwEHA0IABA0vzlsPwQxx9pdqWTuiz5lqjVCprjzUie8W7VcbCKbicDcZ7a3Ieqm1
20
- Nla1Y2Ls0QI0L433/a4AvZCSxovmdjkwCgYIKoZIzj0EAwIDRwAwRAIgWFa5O1DU
21
- knIrEdqRN1AoSccEbIVQM9q3W+IC0xFHeU8CIDOfBI4Tn40oE+85IslFMVLZaXGK
22
- eD4SF5N8kWIN6UxT
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