PyPtt 2.0.5__tar.gz → 2.0.7__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.0.5 → pyptt-2.0.7}/PKG-INFO +1 -1
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/__init__.py +3 -1
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_user.py +33 -25
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_waterball.py +10 -2
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/screens.py +2 -0
- pyptt-2.0.7/PyPtt/ssl_config.py +24 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt.egg-info/PKG-INFO +1 -1
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_user.py +6 -13
- pyptt-2.0.5/PyPtt/ssl_config.py +0 -24
- {pyptt-2.0.5 → pyptt-2.0.7}/LICENSE +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/PTT.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_bucket.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_call_status.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_change_pw.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_comment.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_del_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_board_info.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_board_list.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_bottom_post_list.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_favourite_board.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_newest_index.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_post_index.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_post_list.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_get_time.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_give_money.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_has_new_mail.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_loginout.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_mail.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_mark_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_reply_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_search_user.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_set_board_title.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/_api_util.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/api_server.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/check_value.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/command.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/config.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/connect_core.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/data_type.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/exceptions.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/i18n.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/lang_en_US.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/lang_zh_TW.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/lib_util.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/log.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt/service.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt.egg-info/SOURCES.txt +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt.egg-info/dependency_links.txt +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt.egg-info/requires.txt +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/PyPtt.egg-info/top_level.txt +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/README.md +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/pyproject.toml +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/setup.cfg +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/setup.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_change_pw.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_comment.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_del_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_exceptions.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_board_info.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_board_list.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_bottom_post_list.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_favourite_boards.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_mail.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_newest_index.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_post_list.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_post_parser.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_time.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_get_waterball.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_give_money.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_i18n.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_init.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_logger.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_parse_query_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_reply_post.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_search_user.py +0 -0
- {pyptt-2.0.5 → pyptt-2.0.7}/tests/test_service.py +0 -0
|
@@ -37,30 +37,21 @@ def get_user(api, ptt_id: str) -> Dict:
|
|
|
37
37
|
|
|
38
38
|
cmd = ''.join(cmd_list)
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
api.connect_core.send(cmd, target_list)
|
|
45
|
-
|
|
46
|
-
cmd_list = []
|
|
47
|
-
cmd_list.append('Q')
|
|
48
|
-
cmd_list.append(command.enter)
|
|
49
|
-
cmd_list.append(ptt_id)
|
|
50
|
-
cmd_list.append(command.enter)
|
|
51
|
-
|
|
52
|
-
cmd = ''.join(cmd_list)
|
|
40
|
+
# Use InTalk as a non-break target that auto-responds with the
|
|
41
|
+
# query command, and max_match=1 to prevent re-matching on
|
|
42
|
+
# intermediate screens (race condition fix).
|
|
43
|
+
query_cmd = 'Q' + command.enter + ptt_id + command.enter
|
|
53
44
|
|
|
54
45
|
target_list = [
|
|
55
46
|
connect_core.TargetUnit(screens.Target.AnyKey, break_detect=True),
|
|
56
|
-
connect_core.TargetUnit(screens.Target.InTalk,
|
|
47
|
+
connect_core.TargetUnit(screens.Target.InTalk,
|
|
48
|
+
response=query_cmd,
|
|
49
|
+
max_match=1),
|
|
57
50
|
]
|
|
58
51
|
|
|
59
|
-
index = api.connect_core.send(
|
|
60
|
-
cmd,
|
|
61
|
-
target_list)
|
|
52
|
+
index = api.connect_core.send(cmd, target_list)
|
|
62
53
|
ori_screen = api.connect_core.get_screen_queue()[-1]
|
|
63
|
-
if index
|
|
54
|
+
if index != 0:
|
|
64
55
|
raise exceptions.NoSuchUser(ptt_id)
|
|
65
56
|
# PTT1
|
|
66
57
|
# 《ID暱稱》CodingMan (專業程式 BUG 製造機)《經濟狀況》小康 ($73866)
|
|
@@ -85,7 +76,13 @@ def get_user(api, ptt_id: str) -> Dict:
|
|
|
85
76
|
|
|
86
77
|
# 《個人名片》CodingMan 目前沒有名片
|
|
87
78
|
|
|
88
|
-
lines = ori_screen.split('\n')
|
|
79
|
+
lines = ori_screen.split('\n')
|
|
80
|
+
|
|
81
|
+
def find_line(marker):
|
|
82
|
+
for i, line in enumerate(lines):
|
|
83
|
+
if marker in line:
|
|
84
|
+
return i, line
|
|
85
|
+
return -1, ''
|
|
89
86
|
|
|
90
87
|
def parse_user_info_from_line(line: str) -> (str, str):
|
|
91
88
|
part_0 = line[line.find('》') + 1:]
|
|
@@ -95,9 +92,20 @@ def get_user(api, ptt_id: str) -> Dict:
|
|
|
95
92
|
|
|
96
93
|
return part_0, part_1
|
|
97
94
|
|
|
98
|
-
|
|
95
|
+
id_idx, id_line = find_line('《ID暱稱》')
|
|
96
|
+
login_idx, login_line = find_line('《登入次數》')
|
|
97
|
+
activity_idx, activity_line = find_line('《目前動態》')
|
|
98
|
+
last_login_idx, last_login_line = find_line('《上次上站》')
|
|
99
|
+
chess_idx, chess_line = find_line('《 五子棋 》')
|
|
100
|
+
|
|
101
|
+
if any(idx == -1 for idx in [id_idx, login_idx, activity_idx, last_login_idx, chess_idx]):
|
|
102
|
+
log.logger.debug('get_user_parse_error', ori_screen)
|
|
103
|
+
raise exceptions.UnknownError(f'get_user parse error: {ori_screen}')
|
|
104
|
+
|
|
105
|
+
ptt_id, buff_1 = parse_user_info_from_line(id_line)
|
|
99
106
|
money = int(int_list[0]) if len(int_list := re.findall(r'\d+', buff_1)) > 0 else buff_1
|
|
100
|
-
|
|
107
|
+
|
|
108
|
+
buff_0, buff_1 = parse_user_info_from_line(login_line)
|
|
101
109
|
|
|
102
110
|
login_count = int(re.findall(r'\d+', buff_0)[0])
|
|
103
111
|
account_verified = ('同天內只計一次' in buff_0)
|
|
@@ -109,11 +117,11 @@ def get_user(api, ptt_id: str) -> Dict:
|
|
|
109
117
|
else:
|
|
110
118
|
illegal_post = None
|
|
111
119
|
|
|
112
|
-
activity, mail = parse_user_info_from_line(
|
|
113
|
-
last_login_date, last_login_ip = parse_user_info_from_line(
|
|
114
|
-
five_chess, chess = parse_user_info_from_line(
|
|
120
|
+
activity, mail = parse_user_info_from_line(activity_line)
|
|
121
|
+
last_login_date, last_login_ip = parse_user_info_from_line(last_login_line)
|
|
122
|
+
five_chess, chess = parse_user_info_from_line(chess_line)
|
|
115
123
|
|
|
116
|
-
signature_file = '\n'.join(lines[
|
|
124
|
+
signature_file = '\n'.join(lines[chess_idx + 1:-1]).strip('\n')
|
|
117
125
|
|
|
118
126
|
log.logger.debug('ptt_id', ptt_id)
|
|
119
127
|
log.logger.debug('money', money)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
+
from datetime import datetime
|
|
4
5
|
from typing import List, Dict
|
|
5
6
|
|
|
6
7
|
from . import _api_util
|
|
@@ -19,6 +20,11 @@ _to_target_pattern = re.compile(r'To (\S+):')
|
|
|
19
20
|
_from_target_pattern = re.compile(r'★(\S+) ')
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
def _parse_date(date_str: str) -> datetime:
|
|
24
|
+
"""Parse waterball date string into datetime object."""
|
|
25
|
+
return datetime.strptime(date_str, '%m/%d/%Y %H:%M:%S')
|
|
26
|
+
|
|
27
|
+
|
|
22
28
|
def _merge_continuation_lines(lines: list) -> list:
|
|
23
29
|
merged = []
|
|
24
30
|
i = 0
|
|
@@ -52,7 +58,7 @@ def _parse_waterball_line(line: str) -> Dict | None:
|
|
|
52
58
|
WaterballField.type: WaterballType.SEND,
|
|
53
59
|
WaterballField.target: target,
|
|
54
60
|
WaterballField.content: content,
|
|
55
|
-
WaterballField.date: date,
|
|
61
|
+
WaterballField.date: _parse_date(date),
|
|
56
62
|
}
|
|
57
63
|
elif line.startswith('★'):
|
|
58
64
|
target_match = _from_target_pattern.search(line)
|
|
@@ -66,7 +72,7 @@ def _parse_waterball_line(line: str) -> Dict | None:
|
|
|
66
72
|
WaterballField.type: WaterballType.CATCH,
|
|
67
73
|
WaterballField.target: target,
|
|
68
74
|
WaterballField.content: content,
|
|
69
|
-
WaterballField.date: date,
|
|
75
|
+
WaterballField.date: _parse_date(date),
|
|
70
76
|
}
|
|
71
77
|
return None
|
|
72
78
|
|
|
@@ -128,6 +134,8 @@ def get_waterball(api, post_action: WaterballPostAction = WaterballPostAction.KE
|
|
|
128
134
|
target_list_exit = [
|
|
129
135
|
connect_core.TargetUnit(screens.Target.WaterBallPostAction, log_level=log.DEBUG,
|
|
130
136
|
response=action_cmd + command.enter),
|
|
137
|
+
connect_core.TargetUnit(screens.Target.WaterballCleanup, log_level=log.DEBUG,
|
|
138
|
+
response='y' + command.enter),
|
|
131
139
|
connect_core.TargetUnit(screens.Target.MainMenu, log_level=log.DEBUG, break_detect=True),
|
|
132
140
|
]
|
|
133
141
|
api.connect_core.send('q', target_list_exit)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
key = """-----BEGIN EC PARAMETERS-----
|
|
2
|
+
BggqhkjOPQMBBw==
|
|
3
|
+
-----END EC PARAMETERS-----
|
|
4
|
+
-----BEGIN EC PRIVATE KEY-----
|
|
5
|
+
MHcCAQEEIFvkfPbkl4Ke99iXWTXG1LJnhFeMFREJWW9d4I76PZmGoAoGCCqGSM49
|
|
6
|
+
AwEHoUQDQgAErWNfoKcmEmi+0tNm2CCne7MhF0+4iKZYJvtrn5kxRG73XWhoR79c
|
|
7
|
+
7tfex7gLuFn/VXiP+rgDOe4MLT1LGrtD4A==
|
|
8
|
+
-----END EC PRIVATE KEY-----
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
cert = """-----BEGIN CERTIFICATE-----
|
|
12
|
+
MIIB6TCCAY8CFFzZNObjJZqIs69GFDYbSXJqNpBIMAoGCCqGSM49BAMCMHcxCzAJ
|
|
13
|
+
BgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UE
|
|
14
|
+
CgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25hbCBVbml0MRQw
|
|
15
|
+
EgYDVQQDDAtDb21tb24gTmFtZTAeFw0yNjA0MDMxNDM1MzRaFw0zNjAzMzExNDM1
|
|
16
|
+
MzRaMHcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0
|
|
17
|
+
eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25h
|
|
18
|
+
bCBVbml0MRQwEgYDVQQDDAtDb21tb24gTmFtZTBZMBMGByqGSM49AgEGCCqGSM49
|
|
19
|
+
AwEHA0IABK1jX6CnJhJovtLTZtggp3uzIRdPuIimWCb7a5+ZMURu911oaEe/XO7X
|
|
20
|
+
3se4C7hZ/1V4j/q4AznuDC09Sxq7Q+AwCgYIKoZIzj0EAwIDSAAwRQIhAOAM8IPM
|
|
21
|
+
5D4BoaWYf3SaSVzrm8v6FtSIhWrSYJatYjwoAiAW3NggrC+qYY3wYRDq8UmaiHLv
|
|
22
|
+
pkJCEsbjl+remcwPbg==
|
|
23
|
+
-----END CERTIFICATE-----
|
|
24
|
+
"""
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
def _check_user_info(user_info, test_user):
|
|
2
5
|
assert user_info is not None, f'get_user returned None for user {test_user}'
|
|
3
6
|
assert 'ptt_id' in user_info
|
|
@@ -16,20 +19,10 @@ def test_get_user(ptt_bots):
|
|
|
16
19
|
'CodingMan',
|
|
17
20
|
]
|
|
18
21
|
|
|
19
|
-
for
|
|
22
|
+
for _ in range(100):
|
|
20
23
|
for test_user in test_users:
|
|
21
|
-
user_info =
|
|
24
|
+
user_info = ptt_bots[0].get_user(test_user)
|
|
22
25
|
_check_user_info(user_info, test_user)
|
|
23
26
|
|
|
27
|
+
time.sleep(1)
|
|
24
28
|
|
|
25
|
-
def test_get_user_ptt1_only(ptt_bots):
|
|
26
|
-
"""Tests getting user information that only exists on PTT1."""
|
|
27
|
-
ptt1_bot = ptt_bots[0]
|
|
28
|
-
|
|
29
|
-
test_users = [
|
|
30
|
-
'janice001',
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
for test_user in test_users:
|
|
34
|
-
user_info = ptt1_bot.get_user(test_user)
|
|
35
|
-
_check_user_info(user_info, test_user)
|
pyptt-2.0.5/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
|
-
MHcCAQEEIKoC26Q5VfzkSPN5TShnQWBjUczlLrchp6TUvZz3yUvGoAoGCCqGSM49
|
|
6
|
-
AwEHoUQDQgAE9FSTa74Y+hPSchUFAl0c0oX631NUsDjDZ2BR5/5uZ0CHcPNPiObg
|
|
7
|
-
D3uXFU0vPdGIqDWIDHDf3VmshiDUD9IUgQ==
|
|
8
|
-
-----END EC PRIVATE KEY-----
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
cert = """-----BEGIN CERTIFICATE-----
|
|
12
|
-
MIIB6DCCAY8CFGo6SqurrckTpxffizxr9VUuLqI9MAoGCCqGSM49BAMCMHcxCzAJ
|
|
13
|
-
BgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UE
|
|
14
|
-
CgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25hbCBVbml0MRQw
|
|
15
|
-
EgYDVQQDDAtDb21tb24gTmFtZTAeFw0yNjA0MDIxNTExNTdaFw0zNjAzMzAxNTEx
|
|
16
|
-
NTdaMHcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0
|
|
17
|
-
eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRwwGgYDVQQLDBNPcmdhbml6YXRpb25h
|
|
18
|
-
bCBVbml0MRQwEgYDVQQDDAtDb21tb24gTmFtZTBZMBMGByqGSM49AgEGCCqGSM49
|
|
19
|
-
AwEHA0IABPRUk2u+GPoT0nIVBQJdHNKF+t9TVLA4w2dgUef+bmdAh3DzT4jm4A97
|
|
20
|
-
lxVNLz3RiKg1iAxw391ZrIYg1A/SFIEwCgYIKoZIzj0EAwIDRwAwRAIgSrQ9dTQ9
|
|
21
|
-
qajw32Ws/Ua9s3WvPaPa9QGwmv2Mm1Wk02sCICh8iO5eApwSnSD+PdoTVgrINx72
|
|
22
|
-
aDsfqjLNJ4BPjSDw
|
|
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
|