@artilingo/artiframe-cli 1.3.0 → 1.4.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artilingo/artiframe-cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "ArtiFrame — Zero-dependency native PHP framework with a powerful multilingual CLI. Scaffold projects, generate views, APIs and classes instantly.",
5
5
  "main": "bin/artiframe.js",
6
6
  "bin": {
package/src/App.php CHANGED
@@ -230,6 +230,18 @@ class App
230
230
  (new \ArtiFrame\Cli\Commands\ServeCommand($this->translator))->execute($commandArgs);
231
231
  break;
232
232
 
233
+ case 'auth':
234
+ (new \ArtiFrame\Cli\Commands\AuthCommand($this->translator))->execute($commandArgs);
235
+ break;
236
+
237
+ case 'suggest':
238
+ (new \ArtiFrame\Cli\Commands\SuggestCommand($this->translator))->execute($commandArgs);
239
+ break;
240
+
241
+ case 'issues':
242
+ (new \ArtiFrame\Cli\Commands\IssuesCommand($this->translator))->execute($commandArgs);
243
+ break;
244
+
233
245
  case 'add':
234
246
  (new \ArtiFrame\Cli\Commands\AddCommand($this->translator))->execute($commandArgs);
235
247
  break;
@@ -383,6 +395,24 @@ class App
383
395
  echo " " . $d . "└── " . $r . $lg . "add list" . $r . $d . " " . $t->get('HELP_ADD_LIST') . $r . PHP_EOL;
384
396
  echo PHP_EOL;
385
397
 
398
+ // auth
399
+ echo " " . $g . "auth" . $r . PHP_EOL;
400
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_AUTH_DESC') . PHP_EOL;
401
+ echo " " . $d . "└── " . $r . "Example: " . $lg . "auth" . $r . PHP_EOL;
402
+ echo PHP_EOL;
403
+
404
+ // suggest
405
+ echo " " . $g . "suggest" . $r . PHP_EOL;
406
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_SUGGEST_DESC') . PHP_EOL;
407
+ echo " " . $d . "└── " . $r . "Example: " . $lg . "suggest" . $r . PHP_EOL;
408
+ echo PHP_EOL;
409
+
410
+ // issues
411
+ echo " " . $g . "issues" . $r . " " . $y . "[id]" . $r . PHP_EOL;
412
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_ISSUES_DESC') . PHP_EOL;
413
+ echo " " . $d . "└── " . $r . "Example: " . $lg . "issues" . $r . " or " . $lg . "issues 4" . $r . PHP_EOL;
414
+ echo PHP_EOL;
415
+
386
416
  // help / exit
387
417
  echo " " . $d . "─────────────────────────────────────────────────────────────" . $r . PHP_EOL;
388
418
  echo " " . $g . "help" . $r . " " . $t->get('HELP_HELP_DESC') . PHP_EOL;
@@ -0,0 +1,219 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class AuthCommand
7
+ {
8
+ private Translator $translator;
9
+
10
+ // Placeholder Client ID as requested
11
+ const CLIENT_ID = 'Ov23libWFmWDGtyaSEiT';
12
+
13
+ public function __construct(Translator $translator)
14
+ {
15
+ $this->translator = $translator;
16
+ }
17
+
18
+ public function execute(array $args): void
19
+ {
20
+ echo "\033[1;36mInitializing GitHub Authentication...\033[0m" . PHP_EOL;
21
+
22
+ // 1. Request Device Code
23
+ $deviceCodeData = $this->requestDeviceCode();
24
+ if (!$deviceCodeData) {
25
+ return;
26
+ }
27
+
28
+ $deviceCode = $deviceCodeData['device_code'];
29
+ $userCode = $deviceCodeData['user_code'];
30
+ $verificationUri = $deviceCodeData['verification_uri'];
31
+ $interval = (int)($deviceCodeData['interval'] ?? 5);
32
+
33
+ // 2. Display instructions
34
+ echo PHP_EOL;
35
+ echo "\033[1;33mAction Required:\033[0m" . PHP_EOL;
36
+ echo "1. Please open your browser to: \033[1;34m" . $verificationUri . "\033[0m" . PHP_EOL;
37
+ echo "2. Enter the following code to authorize: \033[1;32m" . $userCode . "\033[0m" . PHP_EOL;
38
+ echo PHP_EOL;
39
+ echo "Waiting for authorization..." . PHP_EOL;
40
+
41
+ // 3. Open browser automatically
42
+ $this->openBrowser($verificationUri);
43
+
44
+ // 4. Poll for Access Token
45
+ $accessToken = $this->pollForToken($deviceCode, $interval);
46
+
47
+ if ($accessToken) {
48
+ // 5. Fetch user profile
49
+ $userProfile = $this->fetchUserProfile($accessToken);
50
+ $username = $userProfile['login'] ?? 'Unknown User';
51
+
52
+ // 6. Save configuration
53
+ $this->saveConfig($accessToken, $username);
54
+
55
+ echo "\033[1;32m✔ Successfully authenticated as @{$username}!\033[0m" . PHP_EOL;
56
+ }
57
+ }
58
+
59
+ private function requestDeviceCode(): ?array
60
+ {
61
+ $ch = curl_init('https://github.com/login/device/code');
62
+ $postData = http_build_query([
63
+ 'client_id' => self::CLIENT_ID,
64
+ 'scope' => 'public_repo'
65
+ ]);
66
+
67
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
68
+ curl_setopt($ch, CURLOPT_POST, true);
69
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
70
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
71
+ 'Accept: application/json'
72
+ ]);
73
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
74
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
75
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
76
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
77
+ curl_setopt($ch, CURLOPT_USERAGENT, 'ArtiFrame-CLI');
78
+
79
+ $response = curl_exec($ch);
80
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
81
+
82
+ if ($httpCode !== 200 || !$response) {
83
+ echo "\033[1;31m[-] Failed to request device code from GitHub.\033[0m" . PHP_EOL;
84
+ curl_close($ch);
85
+ return null;
86
+ }
87
+ curl_close($ch);
88
+
89
+ return json_decode($response, true);
90
+ }
91
+
92
+ private function pollForToken(string $deviceCode, int $interval): ?string
93
+ {
94
+ $url = 'https://github.com/login/oauth/access_token';
95
+
96
+ while (true) {
97
+ sleep($interval);
98
+
99
+ $ch = curl_init($url);
100
+ $postData = http_build_query([
101
+ 'client_id' => self::CLIENT_ID,
102
+ 'device_code' => $deviceCode,
103
+ 'grant_type' => 'urn:ietf:params:oauth:grant-type:device_code'
104
+ ]);
105
+
106
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
107
+ curl_setopt($ch, CURLOPT_POST, true);
108
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
109
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
110
+ 'Accept: application/json'
111
+ ]);
112
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
113
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
114
+ curl_setopt($ch, CURLOPT_USERAGENT, 'ArtiFrame-CLI');
115
+
116
+ $response = curl_exec($ch);
117
+ curl_close($ch);
118
+
119
+ if ($response) {
120
+ $data = json_decode($response, true);
121
+
122
+ if (isset($data['access_token'])) {
123
+ return $data['access_token'];
124
+ }
125
+
126
+ if (isset($data['error'])) {
127
+ if ($data['error'] === 'authorization_pending') {
128
+ // Keep waiting
129
+ continue;
130
+ } elseif ($data['error'] === 'slow_down') {
131
+ $interval += 5; // Slow down polling
132
+ continue;
133
+ } elseif ($data['error'] === 'expired_token') {
134
+ echo "\033[1;31m[-] The device code expired. Please run the auth command again.\033[0m" . PHP_EOL;
135
+ return null;
136
+ } elseif ($data['error'] === 'access_denied') {
137
+ echo "\033[1;31m[-] Authorization was denied.\033[0m" . PHP_EOL;
138
+ return null;
139
+ } else {
140
+ echo "\033[1;31m[-] An error occurred: " . $data['error'] . "\033[0m" . PHP_EOL;
141
+ return null;
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ private function fetchUserProfile(string $token): ?array
149
+ {
150
+ $ch = curl_init('https://api.github.com/user');
151
+
152
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
153
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
154
+ 'Accept: application/vnd.github.v3+json',
155
+ 'Authorization: Bearer ' . $token,
156
+ 'User-Agent: ArtiFrame-CLI'
157
+ ]);
158
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
159
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
160
+
161
+ $response = curl_exec($ch);
162
+ curl_close($ch);
163
+
164
+ if ($response) {
165
+ return json_decode($response, true);
166
+ }
167
+
168
+ return null;
169
+ }
170
+
171
+ private function saveConfig(string $token, string $username): void
172
+ {
173
+ $home = getenv('HOME') ?: getenv('USERPROFILE');
174
+ $configDir = $home . \DIRECTORY_SEPARATOR . '.artiframe';
175
+
176
+ if (!is_dir($configDir)) {
177
+ mkdir($configDir, 0755, true);
178
+ }
179
+
180
+ $configFile = $configDir . \DIRECTORY_SEPARATOR . 'config.json';
181
+
182
+ $config = [];
183
+ if (file_exists($configFile)) {
184
+ $existing = json_decode(file_get_contents($configFile), true);
185
+ if (is_array($existing)) {
186
+ $config = $existing;
187
+ }
188
+ }
189
+
190
+ $config['github_token'] = $token;
191
+ $config['github_user'] = $username;
192
+ $config['logged_in_at'] = date('c');
193
+
194
+ file_put_contents($configFile, json_encode($config, JSON_PRETTY_PRINT));
195
+ }
196
+
197
+ private function openBrowser(string $url): void
198
+ {
199
+ $os = php_uname('s');
200
+ $command = '';
201
+
202
+ if (stripos($os, 'win') === 0) {
203
+ $command = 'start "" "' . $url . '"';
204
+ } elseif (stripos($os, 'darwin') === 0) {
205
+ $command = 'open "' . $url . '"';
206
+ } else {
207
+ $command = 'xdg-open "' . $url . '"';
208
+ }
209
+
210
+ if ($command) {
211
+ // execute command silently in background
212
+ if (stripos($os, 'win') === 0) {
213
+ pclose(popen($command, "r"));
214
+ } else {
215
+ exec($command . ' > /dev/null 2>&1 &');
216
+ }
217
+ }
218
+ }
219
+ }
@@ -0,0 +1,174 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class IssuesCommand
7
+ {
8
+ private Translator $translator;
9
+ const REPO = 'utkuthecoder/artiframe-cli';
10
+
11
+ public function __construct(Translator $translator)
12
+ {
13
+ $this->translator = $translator;
14
+ }
15
+
16
+ public function execute(array $args = []): void
17
+ {
18
+ $home = getenv('HOME') ?: getenv('USERPROFILE');
19
+ $configPath = $home . \DIRECTORY_SEPARATOR . '.artiframe' . \DIRECTORY_SEPARATOR . 'config.json';
20
+
21
+ if (!file_exists($configPath)) {
22
+ echo "\033[1;31m[-] " . $this->translator->get('SUGGEST_NOT_AUTH') . "\033[0m" . PHP_EOL;
23
+ echo "Run: \033[1;32martiframe auth\033[0m" . PHP_EOL;
24
+ return;
25
+ }
26
+
27
+ $config = json_decode(file_get_contents($configPath), true);
28
+ $token = $config['github_token'] ?? null;
29
+ $username = $config['github_user'] ?? null;
30
+
31
+ if (!$token || !$username) {
32
+ echo "\033[1;31m[-] " . $this->translator->get('SUGGEST_NOT_AUTH') . "\033[0m" . PHP_EOL;
33
+ echo "Run: \033[1;32martiframe auth\033[0m" . PHP_EOL;
34
+ return;
35
+ }
36
+
37
+ $issueId = $args[0] ?? null;
38
+
39
+ if ($issueId) {
40
+ $this->showIssueDetails($token, $username, $issueId);
41
+ } else {
42
+ $this->listIssues($token, $username);
43
+ }
44
+ }
45
+
46
+ private function listIssues(string $token, string $username): void
47
+ {
48
+ echo PHP_EOL . "\033[1;36mFetching issues for @{$username}...\033[0m" . PHP_EOL;
49
+
50
+ $url = 'https://api.github.com/repos/' . self::REPO . '/issues?creator=' . urlencode($username) . '&state=all';
51
+ $response = $this->githubApiRequest($url, $token);
52
+
53
+ if (!$response) {
54
+ echo "\033[1;31m[-] Failed to fetch issues from GitHub.\033[0m" . PHP_EOL;
55
+ return;
56
+ }
57
+
58
+ $issues = json_decode($response, true);
59
+
60
+ if (isset($issues['message'])) {
61
+ echo "\033[1;31m[-] GitHub Error: " . $issues['message'] . "\033[0m" . PHP_EOL;
62
+ return;
63
+ }
64
+
65
+ if (empty($issues)) {
66
+ echo "\033[1;33mYou haven't opened any issues yet.\033[0m" . PHP_EOL;
67
+ return;
68
+ }
69
+
70
+ echo "\033[1;37m" . str_pad("ID", 6) . str_pad("STATUS", 10) . str_pad("COMMENTS", 10) . "TITLE\033[0m" . PHP_EOL;
71
+ echo str_repeat("-", 80) . PHP_EOL;
72
+
73
+ foreach ($issues as $issue) {
74
+ if (isset($issue['pull_request'])) {
75
+ continue; // Skip PRs if they show up in issue search
76
+ }
77
+
78
+ $id = "#" . $issue['number'];
79
+ $state = $issue['state']; // open or closed
80
+ $comments = $issue['comments'];
81
+ $title = strlen($issue['title']) > 50 ? substr($issue['title'], 0, 47) . '...' : $issue['title'];
82
+
83
+ $stateColor = $state === 'open' ? "\033[1;32m" : "\033[1;31m"; // Green for open, red for closed
84
+ $displayState = ucfirst($state);
85
+
86
+ echo str_pad($id, 6) .
87
+ $stateColor . str_pad($displayState, 10) . "\033[0m" .
88
+ str_pad((string)$comments, 10) .
89
+ $title . PHP_EOL;
90
+ }
91
+
92
+ echo PHP_EOL . "\033[38;5;240mTip: To view comments for a specific issue, run `artiframe issues <ID>`\033[0m" . PHP_EOL;
93
+ }
94
+
95
+ private function showIssueDetails(string $token, string $username, string $issueId): void
96
+ {
97
+ $issueId = ltrim($issueId, '#');
98
+ echo PHP_EOL . "\033[1;36mFetching details for Issue #{$issueId}...\033[0m" . PHP_EOL;
99
+
100
+ // Fetch Issue Details
101
+ $url = 'https://api.github.com/repos/' . self::REPO . '/issues/' . $issueId;
102
+ $response = $this->githubApiRequest($url, $token);
103
+
104
+ if (!$response) {
105
+ echo "\033[1;31m[-] Failed to fetch issue details.\033[0m" . PHP_EOL;
106
+ return;
107
+ }
108
+
109
+ $issue = json_decode($response, true);
110
+
111
+ if (isset($issue['message'])) {
112
+ echo "\033[1;31m[-] GitHub Error: " . $issue['message'] . "\033[0m" . PHP_EOL;
113
+ return;
114
+ }
115
+
116
+ $stateColor = $issue['state'] === 'open' ? "\033[1;32m" : "\033[1;31m";
117
+
118
+ echo PHP_EOL;
119
+ echo "\033[1;37m[" . $issue['state'] . "] " . $issue['title'] . "\033[0m" . PHP_EOL;
120
+ echo "\033[38;5;240mOpened by @" . $issue['user']['login'] . " at " . date('Y-m-d H:i', strtotime($issue['created_at'])) . "\033[0m" . PHP_EOL;
121
+ echo str_repeat("=", 80) . PHP_EOL;
122
+ echo $this->wordWrapWithIndentation($issue['body']) . PHP_EOL;
123
+ echo str_repeat("=", 80) . PHP_EOL;
124
+
125
+ if ($issue['comments'] > 0) {
126
+ echo PHP_EOL . "\033[1;36mComments ({$issue['comments']}):\033[0m" . PHP_EOL;
127
+
128
+ $commentsUrl = $issue['comments_url'];
129
+ $commentsResponse = $this->githubApiRequest($commentsUrl, $token);
130
+ $comments = json_decode($commentsResponse, true);
131
+
132
+ if (is_array($comments)) {
133
+ foreach ($comments as $comment) {
134
+ echo PHP_EOL;
135
+ echo "\033[1;34m@" . $comment['user']['login'] . "\033[0m \033[38;5;240m(" . date('Y-m-d H:i', strtotime($comment['created_at'])) . "):\033[0m" . PHP_EOL;
136
+ echo str_repeat("-", 80) . PHP_EOL;
137
+ echo $this->wordWrapWithIndentation($comment['body']) . PHP_EOL;
138
+ echo str_repeat("-", 80) . PHP_EOL;
139
+ }
140
+ }
141
+ } else {
142
+ echo PHP_EOL . "\033[38;5;240mNo comments on this issue yet.\033[0m" . PHP_EOL;
143
+ }
144
+ echo PHP_EOL;
145
+ }
146
+
147
+ private function githubApiRequest(string $url, string $token): ?string
148
+ {
149
+ $ch = curl_init($url);
150
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
151
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
152
+ 'Accept: application/vnd.github.v3+json',
153
+ 'Authorization: Bearer ' . $token,
154
+ 'User-Agent: ArtiFrame-CLI'
155
+ ]);
156
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
157
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
158
+
159
+ $response = curl_exec($ch);
160
+ curl_close($ch);
161
+
162
+ return $response ?: null;
163
+ }
164
+
165
+ private function wordWrapWithIndentation(string $text, int $width = 80): string
166
+ {
167
+ $lines = explode("\n", $text);
168
+ $wrapped = [];
169
+ foreach ($lines as $line) {
170
+ $wrapped[] = wordwrap(trim($line), $width, "\n");
171
+ }
172
+ return implode("\n", $wrapped);
173
+ }
174
+ }
@@ -0,0 +1,143 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class SuggestCommand
7
+ {
8
+ private Translator $translator;
9
+ const API_ENDPOINT = 'https://api.artilingo.com/artiframe/v1/suggest.php';
10
+
11
+ public function __construct(Translator $translator)
12
+ {
13
+ $this->translator = $translator;
14
+ }
15
+
16
+ public function execute(array $args): void
17
+ {
18
+ $home = getenv('HOME') ?: getenv('USERPROFILE');
19
+ $configFile = $home . \DIRECTORY_SEPARATOR . '.artiframe' . \DIRECTORY_SEPARATOR . 'config.json';
20
+
21
+ if (!file_exists($configFile)) {
22
+ echo "\033[1;31m[-] Not authenticated. Please run 'artiframe auth' first.\033[0m" . PHP_EOL;
23
+ return;
24
+ }
25
+
26
+ $config = json_decode(file_get_contents($configFile), true);
27
+ if (!$config || !isset($config['github_token'])) {
28
+ echo "\033[1;31m[-] Not authenticated. Please run 'artiframe auth' first.\033[0m" . PHP_EOL;
29
+ return;
30
+ }
31
+
32
+ $token = $config['github_token'];
33
+ $username = $config['github_user'] ?? 'User';
34
+
35
+ echo "\033[1;36mHello @{$username}, welcome to ArtiFrame Issue Submitter!\033[0m" . PHP_EOL;
36
+ echo PHP_EOL;
37
+
38
+ // 1. Ask for Category
39
+ $categories = [
40
+ '1' => 'Feature Request',
41
+ '2' => 'Bug Report',
42
+ '3' => 'Helper Suggestion'
43
+ ];
44
+
45
+ echo "Please select a Category:" . PHP_EOL;
46
+ echo " [1] Feature Request" . PHP_EOL;
47
+ echo " [2] Bug Report" . PHP_EOL;
48
+ echo " [3] Helper Suggestion" . PHP_EOL;
49
+
50
+ $categoryId = null;
51
+ while (true) {
52
+ echo "Select [1-3]: ";
53
+ $input = trim(fgets(STDIN));
54
+ if (isset($categories[$input])) {
55
+ $categoryId = $input;
56
+ break;
57
+ }
58
+ echo "\033[1;31mInvalid selection.\033[0m" . PHP_EOL;
59
+ }
60
+
61
+ $category = $categories[$categoryId];
62
+
63
+ // 2. Ask for Title
64
+ echo PHP_EOL;
65
+ $title = '';
66
+ while (true) {
67
+ echo "Title (Short summary, max 120 chars): ";
68
+ $title = trim(fgets(STDIN));
69
+ if (strlen($title) === 0) {
70
+ echo "\033[1;31mTitle cannot be empty.\033[0m" . PHP_EOL;
71
+ } elseif (strlen($title) > 120) {
72
+ echo "\033[1;31mTitle is too long. Max 120 chars.\033[0m" . PHP_EOL;
73
+ } else {
74
+ break;
75
+ }
76
+ }
77
+
78
+ // 3. Ask for Description
79
+ echo PHP_EOL;
80
+ echo "Description (Detailed explanation or code sample):" . PHP_EOL;
81
+ echo "\033[1;33m(Type 'END' on a new line and press Enter to finish)\033[0m" . PHP_EOL;
82
+
83
+ $bodyLines = [];
84
+ while (true) {
85
+ $line = fgets(STDIN);
86
+ if ($line === false || trim(strtoupper($line)) === 'END') {
87
+ break;
88
+ }
89
+ $bodyLines[] = rtrim($line, "\r\n");
90
+ }
91
+ $body = implode(PHP_EOL, $bodyLines);
92
+
93
+ if (empty(trim($body))) {
94
+ echo "\033[1;31m[-] Description cannot be empty. Aborting.\033[0m" . PHP_EOL;
95
+ return;
96
+ }
97
+
98
+ // 4. Send Payload
99
+ echo PHP_EOL . "\033[1;36mSubmitting to ArtiFrame...\033[0m" . PHP_EOL;
100
+
101
+ $payload = json_encode([
102
+ 'token' => $token,
103
+ 'category' => $category,
104
+ 'title' => $title,
105
+ 'body' => $body
106
+ ]);
107
+
108
+ $ch = curl_init(self::API_ENDPOINT);
109
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
110
+ curl_setopt($ch, CURLOPT_POST, true);
111
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
112
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
113
+ 'Content-Type: application/json',
114
+ 'Accept: application/json'
115
+ ]);
116
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
117
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
118
+ curl_setopt($ch, CURLOPT_USERAGENT, 'ArtiFrame-CLI');
119
+
120
+ $response = curl_exec($ch);
121
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
122
+ curl_close($ch);
123
+
124
+ if ($response) {
125
+ $data = json_decode($response, true);
126
+ if ($httpCode === 200 && isset($data['status']) && $data['status'] === 'success') {
127
+ echo "\033[1;32m🎉 Issue successfully created!\033[0m" . PHP_EOL;
128
+ echo "URL: " . ($data['issue_url'] ?? 'N/A') . PHP_EOL;
129
+ } else {
130
+ if ($data && isset($data['message'])) {
131
+ echo "\033[1;31m[-] Server Error: " . $data['message'] . "\033[0m" . PHP_EOL;
132
+ } else {
133
+ echo "\033[1;31m[-] Server Error: Unknown response format.\033[0m" . PHP_EOL;
134
+ echo "HTTP Code: " . $httpCode . PHP_EOL;
135
+ echo "Raw Response: " . substr($response, 0, 300) . PHP_EOL;
136
+ }
137
+ }
138
+ } else {
139
+ echo "\033[1;31m[-] Failed to communicate with the server.\033[0m" . PHP_EOL;
140
+ echo "cURL Error: " . curl_error($ch) . PHP_EOL;
141
+ }
142
+ }
143
+ }
package/src/Lang/de.php CHANGED
@@ -75,6 +75,8 @@ return [
75
75
  'HELP_MAJOR_DOWN' => 'Letzte Major-Version zurücksetzen.',
76
76
  'HELP_HELP_DESC' => 'Diese Hilfemeldung anzeigen.',
77
77
  'HELP_EXIT_DESC' => 'Die interaktive Shell beenden.',
78
+ 'HELP_AUTH_DESC' => 'Authentifizieren Sie sich bei GitHub, um Vorschläge einzureichen.',
79
+ 'HELP_SUGGEST_DESC' => 'Reichen Sie einen Funktionswunsch, Fehlerbericht oder Vorschlag direkt bei GitHub ein.',
78
80
 
79
81
  // LangCommand
80
82
  'LANG_CURRENT' => 'Aktuelle Sprache:',
package/src/Lang/en.php CHANGED
@@ -75,6 +75,8 @@ return [
75
75
  'HELP_MAJOR_DOWN' => 'Roll back last major release.',
76
76
  'HELP_HELP_DESC' => 'Show this help message.',
77
77
  'HELP_EXIT_DESC' => 'Exit the interactive shell.',
78
+ 'HELP_AUTH_DESC' => 'Authenticate with GitHub to enable issue suggestions.',
79
+ 'HELP_SUGGEST_DESC' => 'Submit a feature request, bug report, or helper suggestion directly to GitHub.',
78
80
 
79
81
  // LangCommand
80
82
  'LANG_CURRENT' => 'Current language:',
package/src/Lang/es.php CHANGED
@@ -75,6 +75,8 @@ return [
75
75
  'HELP_MAJOR_DOWN' => 'Revertir la última versión mayor.',
76
76
  'HELP_HELP_DESC' => 'Mostrar este mensaje de ayuda.',
77
77
  'HELP_EXIT_DESC' => 'Salir del shell interactivo.',
78
+ 'HELP_AUTH_DESC' => 'Autentifícate con GitHub para habilitar las sugerencias de issues.',
79
+ 'HELP_SUGGEST_DESC' => 'Envía una solicitud de función, un informe de error o una sugerencia de ayuda directamente a GitHub.',
78
80
 
79
81
  // LangCommand
80
82
  'LANG_CURRENT' => 'Idioma actual:',
package/src/Lang/fr.php CHANGED
@@ -75,6 +75,8 @@ return [
75
75
  'HELP_MAJOR_DOWN' => 'Annuler la dernière version majeure.',
76
76
  'HELP_HELP_DESC' => 'Afficher ce message d\'aide.',
77
77
  'HELP_EXIT_DESC' => 'Quitter le shell interactif.',
78
+ 'HELP_AUTH_DESC' => 'Authentifiez-vous avec GitHub pour permettre les suggestions.',
79
+ 'HELP_SUGGEST_DESC' => 'Soumettez une demande de fonctionnalité, un rapport de bogue ou une suggestion d\'aide directement sur GitHub.',
78
80
 
79
81
  // LangCommand
80
82
  'LANG_CURRENT' => 'Langue actuelle :',
package/src/Lang/tr.php CHANGED
@@ -74,7 +74,9 @@ return [
74
74
  'HELP_MINOR_DOWN' => 'Son minör sürümün geri alınması.',
75
75
  'HELP_MAJOR_DOWN' => 'Son majör sürümün geri alınması.',
76
76
  'HELP_HELP_DESC' => 'Bu yardım mesajını gösterir.',
77
- 'HELP_EXIT_DESC' => 'İnteraktif kabuğu kapatır.',
77
+ 'HELP_EXIT_DESC' => 'Etkileşimli kabuktan çık.',
78
+ 'HELP_AUTH_DESC' => 'Issue önerileri için GitHub ile kimlik doğrulaması yapın.',
79
+ 'HELP_SUGGEST_DESC' => 'GitHub\'a doğrudan özellik isteği, hata bildirimi veya öneri gönderin.',
78
80
 
79
81
  // LangCommand
80
82
  'LANG_CURRENT' => 'Mevcut dil:',