agoras 2.0.0__py3-none-any.whl
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.
- agoras/__init__.py +3 -0
- agoras/cli/__init__.py +27 -0
- agoras/cli/base.py +71 -0
- agoras/cli/commands/__init__.py +17 -0
- agoras/cli/commands/publish.py +68 -0
- agoras/cli/converter.py +409 -0
- agoras/cli/legacy.py +405 -0
- agoras/cli/main.py +147 -0
- agoras/cli/media_help.py +48 -0
- agoras/cli/migration.py +171 -0
- agoras/cli/platforms/__init__.py +22 -0
- agoras/cli/platforms/discord.py +161 -0
- agoras/cli/platforms/facebook.py +242 -0
- agoras/cli/platforms/instagram.py +176 -0
- agoras/cli/platforms/linkedin.py +171 -0
- agoras/cli/platforms/telegram.py +157 -0
- agoras/cli/platforms/threads.py +158 -0
- agoras/cli/platforms/tiktok.py +246 -0
- agoras/cli/platforms/whatsapp.py +203 -0
- agoras/cli/platforms/x.py +284 -0
- agoras/cli/platforms/youtube.py +190 -0
- agoras/cli/registry.py +161 -0
- agoras/cli/utils/__init__.py +60 -0
- agoras/cli/utils/feed.py +297 -0
- agoras/cli/utils/media_limits.py +114 -0
- agoras/cli/utils/schedule.py +307 -0
- agoras/cli/utils/tokens.py +280 -0
- agoras/cli/utils/unattended_format.py +248 -0
- agoras/cli/validator.py +68 -0
- agoras-2.0.0.dist-info/METADATA +79 -0
- agoras-2.0.0.dist-info/RECORD +34 -0
- agoras-2.0.0.dist-info/WHEEL +5 -0
- agoras-2.0.0.dist-info/entry_points.txt +2 -0
- agoras-2.0.0.dist-info/top_level.txt +1 -0
agoras/__init__.py
ADDED
agoras/cli/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Please refer to AUTHORS.rst for a complete list of Copyright holders.
|
|
4
|
+
# Copyright (C) 2022-2026, Agoras Developers.
|
|
5
|
+
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
Agoras CLI Package.
|
|
20
|
+
|
|
21
|
+
This package provides the command-line interface for agoras, enabling
|
|
22
|
+
interaction with various social media platforms through a unified CLI.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from agoras.common.version import __author__, __email__, __version__
|
|
26
|
+
|
|
27
|
+
__all__ = ['__version__', '__author__', '__email__']
|
agoras/cli/base.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Please refer to AUTHORS.rst for a complete list of Copyright holders.
|
|
4
|
+
# Copyright (C) 2022-2026, Agoras Developers.
|
|
5
|
+
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
Base utilities for CLI.
|
|
20
|
+
|
|
21
|
+
This module provides common helper functions for argument parsing and
|
|
22
|
+
CLI utilities shared across platform commands.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from argparse import ArgumentParser
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def add_common_content_options(parser: ArgumentParser, images: int = 0):
|
|
29
|
+
"""
|
|
30
|
+
Add common content options (text, link, images).
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
parser: ArgumentParser to add options to
|
|
34
|
+
images: Number of image options to add (0-4)
|
|
35
|
+
"""
|
|
36
|
+
content = parser.add_argument_group('Content Options')
|
|
37
|
+
|
|
38
|
+
content.add_argument('--text',
|
|
39
|
+
help='Text content of the post')
|
|
40
|
+
content.add_argument('--link',
|
|
41
|
+
help='URL to include in post')
|
|
42
|
+
|
|
43
|
+
if images > 0:
|
|
44
|
+
for i in range(1, images + 1):
|
|
45
|
+
content.add_argument(f'--image-{i}',
|
|
46
|
+
help=f'Image URL #{i}')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def add_video_options(parser: ArgumentParser, platform: str = None):
|
|
50
|
+
"""
|
|
51
|
+
Add video-specific options.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
parser: ArgumentParser to add options to
|
|
55
|
+
platform: Optional platform key for contract-based --video-url help
|
|
56
|
+
"""
|
|
57
|
+
from .media_help import video_url_help
|
|
58
|
+
|
|
59
|
+
help_text = video_url_help(platform) if platform else 'URL of video file to upload'
|
|
60
|
+
video = parser.add_argument_group('Video Options')
|
|
61
|
+
video.add_argument(
|
|
62
|
+
'--video-url',
|
|
63
|
+
required=True,
|
|
64
|
+
metavar='<url>',
|
|
65
|
+
help=help_text,
|
|
66
|
+
)
|
|
67
|
+
video.add_argument(
|
|
68
|
+
'--video-title',
|
|
69
|
+
metavar='<title>',
|
|
70
|
+
help='Video title/description',
|
|
71
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Please refer to AUTHORS.rst for a complete list of Copyright holders.
|
|
4
|
+
# Copyright (C) 2022-2026, Agoras Developers.
|
|
5
|
+
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Please refer to AUTHORS.rst for a complete list of Copyright holders.
|
|
4
|
+
# Copyright (C) 2022-2026, Agoras Developers.
|
|
5
|
+
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
from agoras.platforms.discord.wrapper import main as discord
|
|
20
|
+
from agoras.platforms.facebook.wrapper import main as facebook
|
|
21
|
+
from agoras.platforms.instagram.wrapper import main as instagram
|
|
22
|
+
from agoras.platforms.linkedin.wrapper import main as linkedin
|
|
23
|
+
from agoras.platforms.telegram.wrapper import main as telegram
|
|
24
|
+
from agoras.platforms.threads.wrapper import main as threads
|
|
25
|
+
from agoras.platforms.tiktok.wrapper import main as tiktok
|
|
26
|
+
from agoras.platforms.whatsapp.wrapper import main as whatsapp
|
|
27
|
+
from agoras.platforms.x.wrapper import main as x
|
|
28
|
+
from agoras.platforms.youtube.wrapper import main as youtube
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main(**kwargs):
|
|
32
|
+
import sys
|
|
33
|
+
import warnings
|
|
34
|
+
|
|
35
|
+
network = kwargs.get('network')
|
|
36
|
+
|
|
37
|
+
if network == 'x':
|
|
38
|
+
x(kwargs)
|
|
39
|
+
elif network == 'twitter':
|
|
40
|
+
print("Warning: The 'twitter' network name is deprecated. Use 'x' instead.", file=sys.stderr)
|
|
41
|
+
warnings.warn(
|
|
42
|
+
"The 'twitter' network name is deprecated. Use 'x' instead.",
|
|
43
|
+
DeprecationWarning,
|
|
44
|
+
stacklevel=2
|
|
45
|
+
)
|
|
46
|
+
x(kwargs)
|
|
47
|
+
elif network == 'facebook':
|
|
48
|
+
facebook(kwargs)
|
|
49
|
+
elif network == 'instagram':
|
|
50
|
+
instagram(kwargs)
|
|
51
|
+
elif network == 'linkedin':
|
|
52
|
+
linkedin(kwargs)
|
|
53
|
+
elif network == 'discord':
|
|
54
|
+
discord(kwargs)
|
|
55
|
+
elif network == 'youtube':
|
|
56
|
+
youtube(kwargs)
|
|
57
|
+
elif network == 'tiktok':
|
|
58
|
+
tiktok(kwargs)
|
|
59
|
+
elif network == 'threads':
|
|
60
|
+
threads(kwargs)
|
|
61
|
+
elif network == 'telegram':
|
|
62
|
+
telegram(kwargs)
|
|
63
|
+
elif network == 'whatsapp':
|
|
64
|
+
whatsapp(kwargs)
|
|
65
|
+
elif network == '':
|
|
66
|
+
raise Exception('--network is a required argument.')
|
|
67
|
+
else:
|
|
68
|
+
raise Exception(f'"{network}" network not supported.')
|
agoras/cli/converter.py
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Please refer to AUTHORS.rst for a complete list of Copyright holders.
|
|
4
|
+
# Copyright (C) 2022-2026, Agoras Developers.
|
|
5
|
+
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
Parameter converter for CLI.
|
|
20
|
+
|
|
21
|
+
This module converts between new and legacy parameter formats.
|
|
22
|
+
This is a skeleton implementation to be fully populated in later phases.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from argparse import Namespace
|
|
26
|
+
from typing import Any, Dict
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ParameterConverter:
|
|
30
|
+
"""Convert between new and legacy parameter formats."""
|
|
31
|
+
|
|
32
|
+
# Platform-specific parameter mappings
|
|
33
|
+
# To be fully populated in Phase 3 (Week 5)
|
|
34
|
+
PLATFORM_MAPPINGS: Dict[str, Dict[str, str]] = {
|
|
35
|
+
'x': {
|
|
36
|
+
# Auth
|
|
37
|
+
'consumer_key': 'twitter_consumer_key',
|
|
38
|
+
'consumer_secret': 'twitter_consumer_secret',
|
|
39
|
+
'oauth_token': 'twitter_oauth_token',
|
|
40
|
+
'oauth_secret': 'twitter_oauth_secret',
|
|
41
|
+
# Content
|
|
42
|
+
'post_id': 'tweet_id',
|
|
43
|
+
'video_url': 'twitter_video_url',
|
|
44
|
+
'video_title': 'twitter_video_title',
|
|
45
|
+
},
|
|
46
|
+
'twitter': {
|
|
47
|
+
# Auth
|
|
48
|
+
'consumer_key': 'twitter_consumer_key',
|
|
49
|
+
'consumer_secret': 'twitter_consumer_secret',
|
|
50
|
+
'oauth_token': 'twitter_oauth_token',
|
|
51
|
+
'oauth_secret': 'twitter_oauth_secret',
|
|
52
|
+
# Content
|
|
53
|
+
'post_id': 'tweet_id',
|
|
54
|
+
'video_url': 'twitter_video_url',
|
|
55
|
+
'video_title': 'twitter_video_title',
|
|
56
|
+
},
|
|
57
|
+
'facebook': {
|
|
58
|
+
'client_id': 'facebook_client_id',
|
|
59
|
+
'client_secret': 'facebook_client_secret',
|
|
60
|
+
'app_id': 'facebook_app_id',
|
|
61
|
+
'object_id': 'facebook_object_id',
|
|
62
|
+
'post_id': 'facebook_post_id',
|
|
63
|
+
'profile_id': 'facebook_profile_id',
|
|
64
|
+
'video_url': 'facebook_video_url',
|
|
65
|
+
'video_title': 'facebook_video_title',
|
|
66
|
+
'video_description': 'facebook_video_description',
|
|
67
|
+
'video_type': 'facebook_video_type',
|
|
68
|
+
},
|
|
69
|
+
'instagram': {
|
|
70
|
+
'client_id': 'instagram_client_id',
|
|
71
|
+
'client_secret': 'instagram_client_secret',
|
|
72
|
+
'object_id': 'instagram_object_id',
|
|
73
|
+
'post_id': 'instagram_post_id',
|
|
74
|
+
'video_url': 'instagram_video_url',
|
|
75
|
+
'video_caption': 'instagram_video_caption',
|
|
76
|
+
'video_type': 'instagram_video_type',
|
|
77
|
+
},
|
|
78
|
+
'linkedin': {
|
|
79
|
+
'client_id': 'linkedin_client_id',
|
|
80
|
+
'client_secret': 'linkedin_client_secret',
|
|
81
|
+
'object_id': 'linkedin_object_id',
|
|
82
|
+
'post_id': 'linkedin_post_id',
|
|
83
|
+
'video_url': 'linkedin_video_url',
|
|
84
|
+
'video_title': 'linkedin_video_title',
|
|
85
|
+
},
|
|
86
|
+
'discord': {
|
|
87
|
+
'bot_token': 'discord_bot_token',
|
|
88
|
+
'server_name': 'discord_server_name',
|
|
89
|
+
'channel_name': 'discord_channel_name',
|
|
90
|
+
'post_id': 'discord_post_id',
|
|
91
|
+
'video_url': 'discord_video_url',
|
|
92
|
+
'video_title': 'discord_video_title',
|
|
93
|
+
},
|
|
94
|
+
'youtube': {
|
|
95
|
+
'client_id': 'youtube_client_id',
|
|
96
|
+
'client_secret': 'youtube_client_secret',
|
|
97
|
+
'video_id': 'youtube_video_id',
|
|
98
|
+
'video_url': 'youtube_video_url',
|
|
99
|
+
'title': 'youtube_title',
|
|
100
|
+
'description': 'youtube_description',
|
|
101
|
+
'category_id': 'youtube_category_id',
|
|
102
|
+
'privacy': 'youtube_privacy_status',
|
|
103
|
+
'keywords': 'youtube_keywords',
|
|
104
|
+
},
|
|
105
|
+
'tiktok': {
|
|
106
|
+
'client_key': 'tiktok_client_key',
|
|
107
|
+
'client_secret': 'tiktok_client_secret',
|
|
108
|
+
'username': 'tiktok_username',
|
|
109
|
+
'video_url': 'tiktok_video_url',
|
|
110
|
+
'title': 'tiktok_title',
|
|
111
|
+
'privacy': 'tiktok_privacy_status',
|
|
112
|
+
'allow_comments': 'tiktok_allow_comments',
|
|
113
|
+
'allow_duet': 'tiktok_allow_duet',
|
|
114
|
+
'allow_stitch': 'tiktok_allow_stitch',
|
|
115
|
+
'auto_add_music': 'tiktok_auto_add_music',
|
|
116
|
+
'description': 'tiktok_description',
|
|
117
|
+
},
|
|
118
|
+
'threads': {
|
|
119
|
+
'app_id': 'threads_app_id',
|
|
120
|
+
'app_secret': 'threads_app_secret',
|
|
121
|
+
'post_id': 'threads_post_id',
|
|
122
|
+
'video_url': 'threads_video_url',
|
|
123
|
+
'video_title': 'threads_video_title',
|
|
124
|
+
},
|
|
125
|
+
'telegram': {
|
|
126
|
+
'bot_token': 'telegram_bot_token',
|
|
127
|
+
'chat_id': 'telegram_chat_id',
|
|
128
|
+
'parse_mode': 'telegram_parse_mode',
|
|
129
|
+
'message_id': 'telegram_message_id',
|
|
130
|
+
'post_id': 'telegram_message_id',
|
|
131
|
+
'video_url': 'video_url',
|
|
132
|
+
'video_title': 'video_title',
|
|
133
|
+
},
|
|
134
|
+
'whatsapp': {
|
|
135
|
+
'access_token': 'whatsapp_access_token',
|
|
136
|
+
'phone_number_id': 'whatsapp_phone_number_id',
|
|
137
|
+
'business_account_id': 'whatsapp_business_account_id',
|
|
138
|
+
'recipient': 'whatsapp_recipient',
|
|
139
|
+
'message_id': 'whatsapp_message_id',
|
|
140
|
+
'template_name': 'whatsapp_template_name',
|
|
141
|
+
'language_code': 'whatsapp_template_language',
|
|
142
|
+
'template_components': 'whatsapp_template_components',
|
|
143
|
+
'video_url': 'video_url',
|
|
144
|
+
'video_title': 'video_title',
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# Common parameter mappings (apply to all platforms)
|
|
149
|
+
COMMON_MAPPINGS = {
|
|
150
|
+
# Content parameters
|
|
151
|
+
'text': 'status_text',
|
|
152
|
+
'link': 'status_link',
|
|
153
|
+
'image_1': 'status_image_url_1',
|
|
154
|
+
'image_2': 'status_image_url_2',
|
|
155
|
+
'image_3': 'status_image_url_3',
|
|
156
|
+
'image_4': 'status_image_url_4',
|
|
157
|
+
# Feed parameters
|
|
158
|
+
'feed_url': 'feed_url',
|
|
159
|
+
'max_count': 'feed_max_count',
|
|
160
|
+
'post_lookback': 'feed_post_lookback',
|
|
161
|
+
'max_post_age': 'feed_max_post_age',
|
|
162
|
+
# Google Sheets parameters
|
|
163
|
+
'sheets_id': 'google_sheets_id',
|
|
164
|
+
'sheets_name': 'google_sheets_name',
|
|
165
|
+
'sheets_client_email': 'google_sheets_client_email',
|
|
166
|
+
'sheets_private_key': 'google_sheets_private_key',
|
|
167
|
+
# System parameters
|
|
168
|
+
'loglevel': 'loglevel',
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
def __init__(self, platform: str):
|
|
172
|
+
"""
|
|
173
|
+
Initialize parameter converter for a specific platform.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
platform: Platform name
|
|
177
|
+
"""
|
|
178
|
+
self.platform = platform
|
|
179
|
+
self.platform_mapping = self.PLATFORM_MAPPINGS.get(platform, {})
|
|
180
|
+
|
|
181
|
+
def convert_to_legacy(self, args: Namespace) -> Dict[str, Any]:
|
|
182
|
+
"""
|
|
183
|
+
Convert new CLI args to legacy format for core modules.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
args: Parsed arguments from new CLI
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
Dictionary of legacy-format arguments
|
|
190
|
+
"""
|
|
191
|
+
legacy_args = {
|
|
192
|
+
'network': self.platform,
|
|
193
|
+
'action': getattr(args, 'action', None),
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
# Convert platform-specific parameters
|
|
197
|
+
for new_param, value in vars(args).items():
|
|
198
|
+
# Skip None values
|
|
199
|
+
if value is None:
|
|
200
|
+
continue
|
|
201
|
+
|
|
202
|
+
# Skip empty strings (edge case handling)
|
|
203
|
+
if isinstance(value, str) and value.strip() == '':
|
|
204
|
+
continue
|
|
205
|
+
|
|
206
|
+
# Check platform-specific mapping
|
|
207
|
+
if new_param in self.platform_mapping:
|
|
208
|
+
legacy_param = self.platform_mapping[new_param]
|
|
209
|
+
legacy_args[legacy_param] = value
|
|
210
|
+
# Check common mapping
|
|
211
|
+
elif new_param in self.COMMON_MAPPINGS:
|
|
212
|
+
legacy_param = self.COMMON_MAPPINGS[new_param]
|
|
213
|
+
legacy_args[legacy_param] = value
|
|
214
|
+
# Pass through unchanged
|
|
215
|
+
else:
|
|
216
|
+
legacy_args[new_param] = value
|
|
217
|
+
|
|
218
|
+
return legacy_args
|
|
219
|
+
|
|
220
|
+
def convert_from_legacy(self, legacy_args: Dict[str, Any]) -> Dict[str, Any]:
|
|
221
|
+
"""
|
|
222
|
+
Convert legacy args to new format.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
legacy_args: Legacy format arguments
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Dictionary of new-format arguments
|
|
229
|
+
"""
|
|
230
|
+
new_args = {}
|
|
231
|
+
|
|
232
|
+
# Create reverse mappings
|
|
233
|
+
platform_reverse = {v: k for k, v in self.platform_mapping.items()}
|
|
234
|
+
common_reverse = {v: k for k, v in self.COMMON_MAPPINGS.items()}
|
|
235
|
+
|
|
236
|
+
for legacy_param, value in legacy_args.items():
|
|
237
|
+
# Skip None values
|
|
238
|
+
if value is None:
|
|
239
|
+
continue
|
|
240
|
+
|
|
241
|
+
# Skip empty strings (edge case handling)
|
|
242
|
+
if isinstance(value, str) and value.strip() == '':
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
# Check platform-specific reverse mapping
|
|
246
|
+
if legacy_param in platform_reverse:
|
|
247
|
+
new_param = platform_reverse[legacy_param]
|
|
248
|
+
new_args[new_param] = value
|
|
249
|
+
# Check common reverse mapping
|
|
250
|
+
elif legacy_param in common_reverse:
|
|
251
|
+
new_param = common_reverse[legacy_param]
|
|
252
|
+
new_args[new_param] = value
|
|
253
|
+
# Pass through
|
|
254
|
+
else:
|
|
255
|
+
new_args[legacy_param] = value
|
|
256
|
+
|
|
257
|
+
return new_args
|
|
258
|
+
|
|
259
|
+
def convert_to_legacy_with_validation(self, args: Namespace) -> Dict[str, Any]:
|
|
260
|
+
"""
|
|
261
|
+
Convert new CLI args to legacy format with validation.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
args: Parsed arguments from new CLI
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Dictionary of legacy-format arguments
|
|
268
|
+
|
|
269
|
+
Raises:
|
|
270
|
+
ValueError: If validation fails
|
|
271
|
+
"""
|
|
272
|
+
legacy_args = self.convert_to_legacy(args)
|
|
273
|
+
self.validate_legacy_args(legacy_args)
|
|
274
|
+
return legacy_args
|
|
275
|
+
|
|
276
|
+
def validate_legacy_args(self, legacy_args: Dict[str, Any]) -> None:
|
|
277
|
+
"""
|
|
278
|
+
Validate that required legacy parameters are present.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
legacy_args: Legacy format arguments
|
|
282
|
+
|
|
283
|
+
Raises:
|
|
284
|
+
ValueError: If required parameters are missing
|
|
285
|
+
"""
|
|
286
|
+
# Check that network and action are present
|
|
287
|
+
if not legacy_args.get('network'):
|
|
288
|
+
raise ValueError("Missing required parameter: network")
|
|
289
|
+
if not legacy_args.get('action'):
|
|
290
|
+
raise ValueError("Missing required parameter: action")
|
|
291
|
+
|
|
292
|
+
def get_unmapped_parameters(self, args: Namespace) -> list:
|
|
293
|
+
"""
|
|
294
|
+
Get list of parameters that weren't converted (pass-through).
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
args: Parsed arguments from new CLI
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
List of parameter names that weren't mapped
|
|
301
|
+
"""
|
|
302
|
+
unmapped = []
|
|
303
|
+
|
|
304
|
+
for param, value in vars(args).items():
|
|
305
|
+
if value is None:
|
|
306
|
+
continue
|
|
307
|
+
|
|
308
|
+
# Skip special parameters
|
|
309
|
+
if param in ['handler', 'action', 'network']:
|
|
310
|
+
continue
|
|
311
|
+
|
|
312
|
+
# Check if parameter was mapped
|
|
313
|
+
is_platform_mapped = param in self.platform_mapping
|
|
314
|
+
is_common_mapped = param in self.COMMON_MAPPINGS
|
|
315
|
+
|
|
316
|
+
if not is_platform_mapped and not is_common_mapped:
|
|
317
|
+
unmapped.append(param)
|
|
318
|
+
|
|
319
|
+
return unmapped
|
|
320
|
+
|
|
321
|
+
@classmethod
|
|
322
|
+
def get_all_mappings(cls, platform: str = None) -> Dict[str, Any]:
|
|
323
|
+
"""
|
|
324
|
+
Get complete mapping reference for debugging.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
platform: Optional platform to get specific mappings
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Dictionary with all mapping information
|
|
331
|
+
"""
|
|
332
|
+
if platform:
|
|
333
|
+
return {
|
|
334
|
+
'platform': platform,
|
|
335
|
+
'platform_mappings': cls.PLATFORM_MAPPINGS.get(platform, {}),
|
|
336
|
+
'common_mappings': cls.COMMON_MAPPINGS,
|
|
337
|
+
}
|
|
338
|
+
else:
|
|
339
|
+
return {
|
|
340
|
+
'all_platforms': cls.PLATFORM_MAPPINGS,
|
|
341
|
+
'common_mappings': cls.COMMON_MAPPINGS,
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
def log_conversion(self, args: Namespace, legacy_args: Dict[str, Any]) -> None:
|
|
345
|
+
"""
|
|
346
|
+
Log parameter conversion details for debugging.
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
args: Original new-format arguments
|
|
350
|
+
legacy_args: Converted legacy-format arguments
|
|
351
|
+
"""
|
|
352
|
+
print(f"\n=== Parameter Conversion Debug ({self.platform}) ===")
|
|
353
|
+
print(f"Action: {args.action}")
|
|
354
|
+
print("\nNew format parameters:")
|
|
355
|
+
for key, value in vars(args).items():
|
|
356
|
+
if value is not None and key not in ['handler']:
|
|
357
|
+
print(f" {key}: {value}")
|
|
358
|
+
print("\nConverted to legacy format:")
|
|
359
|
+
for key, value in legacy_args.items():
|
|
360
|
+
if value is not None:
|
|
361
|
+
print(f" {key}: {value}")
|
|
362
|
+
print("=" * 50)
|
|
363
|
+
|
|
364
|
+
def get_conversion_report(self, args: Namespace) -> Dict[str, Any]:
|
|
365
|
+
"""
|
|
366
|
+
Generate detailed conversion report for debugging.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
args: Parsed arguments from new CLI
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
Dictionary with conversion details
|
|
373
|
+
"""
|
|
374
|
+
legacy_args = self.convert_to_legacy(args)
|
|
375
|
+
unmapped = self.get_unmapped_parameters(args)
|
|
376
|
+
|
|
377
|
+
# Count conversions
|
|
378
|
+
platform_conversions = []
|
|
379
|
+
common_conversions = []
|
|
380
|
+
pass_through = []
|
|
381
|
+
|
|
382
|
+
for param, value in vars(args).items():
|
|
383
|
+
if value is None or param in ['handler', 'action', 'network']:
|
|
384
|
+
continue
|
|
385
|
+
|
|
386
|
+
if param in self.platform_mapping:
|
|
387
|
+
platform_conversions.append({
|
|
388
|
+
'new': param,
|
|
389
|
+
'legacy': self.platform_mapping[param],
|
|
390
|
+
'value': value
|
|
391
|
+
})
|
|
392
|
+
elif param in self.COMMON_MAPPINGS:
|
|
393
|
+
common_conversions.append({
|
|
394
|
+
'new': param,
|
|
395
|
+
'legacy': self.COMMON_MAPPINGS[param],
|
|
396
|
+
'value': value
|
|
397
|
+
})
|
|
398
|
+
else:
|
|
399
|
+
pass_through.append({'param': param, 'value': value})
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
'platform': self.platform,
|
|
403
|
+
'action': getattr(args, 'action', None),
|
|
404
|
+
'platform_conversions': platform_conversions,
|
|
405
|
+
'common_conversions': common_conversions,
|
|
406
|
+
'pass_through': pass_through,
|
|
407
|
+
'unmapped_params': unmapped,
|
|
408
|
+
'legacy_args': legacy_args,
|
|
409
|
+
}
|