Skip to content

Commit f5ef4c6

Browse files
Merge branch 'main' into feat.pingCMD
2 parents 7ed6ea7 + e9e98c5 commit f5ef4c6

File tree

11 files changed

+199
-74
lines changed

11 files changed

+199
-74
lines changed

.github/workflows/auto-reply.yml

Lines changed: 65 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ name: 🤖 Auto Reply to Issues & PRs
33
on:
44
issues:
55
types: [opened, reopened]
6-
# Use pull_request_target so this job can write comments/labels on PRs from forks.
7-
# SECURITY: Do NOT check out or execute untrusted PR code in this workflow.
86
pull_request_target:
9-
types: [opened, reopened]
7+
types: [opened, reopened, synchronize]
108

119
permissions:
1210
issues: write
@@ -23,82 +21,105 @@ jobs:
2321
script: |
2422
const repo = context.repo;
2523
26-
// Issue opened/reopened
27-
if (context.payload.issue) {
28-
const issue = context.payload.issue;
29-
const user = issue.user?.login || 'contributor';
30-
const issueNumber = issue.number;
31-
const message = `👋 Hi @${user}!\n\nThanks for opening an issue in **MyCMD**.\n\nWe’ll review it soon — please ensure reproduction steps and logs are included.`;
32-
33-
await github.rest.issues.createComment({
24+
async function commentExists(issue_number, messageSnippet) {
25+
const comments = await github.rest.issues.listComments({
3426
owner: repo.owner,
3527
repo: repo.repo,
36-
issue_number: issueNumber,
37-
body: message
28+
issue_number
3829
});
30+
return comments.data.some(c => c.body.includes(messageSnippet));
31+
}
3932
40-
await github.rest.reactions.createForIssue({
33+
async function addReaction(issue_number, reaction) {
34+
const reactions = await github.rest.reactions.listForIssue({
4135
owner: repo.owner,
4236
repo: repo.repo,
43-
issue_number: issueNumber,
44-
content: "tada"
37+
issue_number
4538
});
39+
if (!reactions.data.some(r => r.content === reaction)) {
40+
await github.rest.reactions.createForIssue({
41+
owner: repo.owner,
42+
repo: repo.repo,
43+
issue_number,
44+
content: reaction
45+
});
46+
}
47+
}
4648
49+
async function addLabels(issue_number, labels) {
4750
try {
4851
await github.rest.issues.addLabels({
4952
owner: repo.owner,
5053
repo: repo.repo,
51-
issue_number: issueNumber,
52-
labels: ["triage", "needs-info"]
54+
issue_number,
55+
labels
5356
});
5457
} catch (err) {
55-
core && core.info && core.info("Could not add labels to issue: " + err.message);
58+
core?.info?.("Could not add labels: " + err.message);
5659
}
57-
58-
return;
5960
}
6061
61-
// Pull request opened/reopened (or synchronized)
62+
// Handle Pull Requests
6263
if (context.payload.pull_request) {
6364
const pr = context.payload.pull_request;
6465
const user = pr.user?.login || 'contributor';
6566
const prNumber = pr.number;
6667
67-
const message = `🚀 Hi @${user}!\n\nThank you for contributing to **MyCMD**. A maintainer will review your PR shortly. 🎉`;
68+
const message = `🚀 Hi @${user}!
6869
69-
await github.rest.issues.createComment({
70-
owner: repo.owner,
71-
repo: repo.repo,
72-
issue_number: prNumber,
73-
body: message
74-
});
70+
Thank you for contributing to **MyCMD**. A maintainer will review your PR shortly. 🎉
7571

76-
await github.rest.reactions.createForIssue({
77-
owner: repo.owner,
78-
repo: repo.repo,
79-
issue_number: prNumber,
80-
content: "rocket"
81-
});
72+
### Thank you for raising this issue!
73+
We'll review it as soon as possible. We truly appreciate your contributions! ✨ Meanwhile make sure you've visited the README.md, CONTRIBUTING.md, and CODE_OF_CONDUCT.md before creating a PR for this. Also, please do NOT create a PR until this issue has been assigned to you. 😊`;
74+
75+
const gif = "![TrustTheProcess](https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExbWtoOWpsMnozdXd0MmJxejhiNGwwdjltY3dyNW80NHg2Ym01YTdlMSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/mPKa6OI5oRsmextwBq/giphy.gif)";
76+
77+
if (!(await commentExists(prNumber, "Thank you for contributing to **MyCMD**"))) {
78+
await github.rest.issues.createComment({
79+
owner: repo.owner,
80+
repo: repo.repo,
81+
issue_number: prNumber,
82+
body: message + "\n\n" + gif
83+
});
84+
}
85+
86+
await addReaction(prNumber, "rocket");
8287

83-
const headRepoFull = pr.head && pr.head.repo && pr.head.repo.full_name ? pr.head.repo.full_name : '';
88+
const headRepoFull = pr.head?.repo?.full_name || '';
8489
const baseFull = `${repo.owner}/${repo.repo}`;
8590
const isFork = headRepoFull.toLowerCase() !== baseFull.toLowerCase();
86-
8791
const labels = ["needs-review"];
8892
if (isFork) labels.push("from-fork");
8993

90-
try {
91-
await github.rest.issues.addLabels({
94+
await addLabels(prNumber, labels);
95+
96+
return;
97+
}
98+
99+
// Handle Issues
100+
if (context.payload.issue) {
101+
const issue = context.payload.issue;
102+
const user = issue.user?.login || 'contributor';
103+
const issueNumber = issue.number;
104+
105+
const message = `👋 Hi @${user}!
106+
107+
Thanks for opening an issue in **MyCMD**. We’ll review it soon — please ensure reproduction steps and logs are included.`;
108+
109+
if (!(await commentExists(issueNumber, "Thanks for opening an issue in **MyCMD**"))) {
110+
await github.rest.issues.createComment({
92111
owner: repo.owner,
93112
repo: repo.repo,
94-
issue_number: prNumber,
95-
labels: labels
113+
issue_number: issueNumber,
114+
body: message
96115
});
97-
} catch (err) {
98-
core && core.info && core.info("Could not add labels to PR: " + err.message);
99116
}
100117

118+
await addReaction(issueNumber, "tada");
119+
120+
await addLabels(issueNumber, ["triage", "needs-info"]);
121+
101122
return;
102123
}
103124

104-
core && core.info && core.info('No issue or pull_request payload found. Nothing to do.');
125+
core?.info?.('No issue or pull_request payload found. Nothing to do.');

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target/

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
</p>
55

6+
67
# 💻 MyCMD – A Custom Command Prompt in Java
78

89
![Build](https://img.shields.io/badge/build-passing-brightgreen)
@@ -150,3 +151,4 @@ You are free to use, modify, and distribute.
150151

151152

152153
<img src="https://capsule-render.vercel.app/api?type=waving&color=gradient&customColorList=6,11,20&height=120&section=footer&text=Java,%20Java,%20and%20My%20Java&fontSize=20&fontColor=fff&animation=twinkling"/>
154+

src/main/java/com/mycmd/App.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,8 @@ private static void registerCommands(Map<String, Command> commands) {
7878
commands.put("date", new DateCommand());
7979
commands.put("history", new HistoryCommand());
8080
commands.put("ping", new PingCommand());
81+
commands.put("pwd", new PwdCommand());
82+
commands.put("uptime", new UptimeCommand());
83+
commands.put("clearhistory", new ClearHistoryCommand());
8184
}
8285
}

src/main/java/com/mycmd/ShellContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
public class ShellContext {
88
private File currentDir;
99
private List<String> commandHistory;
10+
private final long startTime;
1011
private static final int MAX_HISTORY = 10;
1112

1213
public ShellContext() {
1314
this.currentDir = new File(System.getProperty("user.dir"));
1415
this.commandHistory = new ArrayList<>();
16+
this.startTime = System.currentTimeMillis();
1517
}
1618

1719
public File getCurrentDir() {
@@ -22,6 +24,10 @@ public void setCurrentDir(File dir) {
2224
this.currentDir = dir;
2325
}
2426

27+
public long getStartTime() {
28+
return startTime;
29+
}
30+
2531
public List<String> getCommandHistory() {
2632
return commandHistory;
2733
}
@@ -35,6 +41,10 @@ public void addToHistory(String command) {
3541
}
3642
}
3743

44+
public void clearHistory() {
45+
commandHistory.clear();
46+
}
47+
3848
/**
3949
* Resolve the given path (absolute or relative) to a File using the current directory.
4050
* If the provided path is absolute, returns it directly; otherwise returns a File rooted at currentDir.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.mycmd.commands;
2+
3+
import com.mycmd.Command;
4+
import com.mycmd.ShellContext;
5+
6+
/**
7+
* Clears the stored command history.
8+
*
9+
* This command removes all previously executed commands from the shell's
10+
* command history. After execution, the history list will be empty and
11+
* the history command will show no previous commands.
12+
*
13+
* Usage:
14+
* - clearhistory : Clear all stored command history
15+
*
16+
* This is useful for privacy purposes or when you want to start fresh
17+
* with a clean command history. The history is cleared immediately
18+
* and cannot be recovered.
19+
*/
20+
public class ClearHistoryCommand implements Command {
21+
@Override
22+
public void execute(String[] args, ShellContext context) {
23+
context.clearHistory();
24+
System.out.println("Command history cleared.");
25+
}
26+
27+
@Override
28+
public String description() {
29+
return "Clear the stored command history.";
30+
}
31+
32+
@Override
33+
public String usage() {
34+
return "clearhistory";
35+
}
36+
}

src/main/java/com/mycmd/commands/HelpCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public HelpCommand(Map<String, Command> commands) {
2020
@Override
2121
public void execute(String[] args, ShellContext context) {
2222
// Detailed help for a specific command
23-
if (args.length > 1) {
24-
String cmdName = args[1];
23+
if (args.length > 0) {
24+
String cmdName = args[0];
2525
Command cmd = commands.get(cmdName);
2626

2727
if (cmd != null) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.mycmd.commands;
2+
3+
import com.mycmd.Command;
4+
import com.mycmd.ShellContext;
5+
6+
/**
7+
* Prints the current working directory.
8+
*
9+
* This command displays the absolute path of the current working directory
10+
* stored in the shell context. It's equivalent to the Unix/Linux 'pwd' command
11+
* and provides the same functionality as 'cd' without arguments.
12+
*
13+
* Usage:
14+
* - pwd : Print the current working directory path
15+
*
16+
* The command always prints the absolute path of the current directory,
17+
* making it useful for scripts and when you need to know your exact location
18+
* in the file system.
19+
*/
20+
public class PwdCommand implements Command {
21+
@Override
22+
public void execute(String[] args, ShellContext context) {
23+
System.out.println(context.getCurrentDir().getAbsolutePath());
24+
}
25+
26+
@Override
27+
public String description() {
28+
return "Print the current working directory path.";
29+
}
30+
31+
@Override
32+
public String usage() {
33+
return "pwd";
34+
}
35+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.mycmd.commands;
2+
3+
import com.mycmd.Command;
4+
import com.mycmd.ShellContext;
5+
6+
/**
7+
* Displays how long the shell has been running since startup.
8+
*
9+
* This command shows the uptime of the MyCMD shell session, displaying
10+
* the time elapsed since the shell was started. The uptime is calculated
11+
* from the shell start time stored in the ShellContext.
12+
*
13+
* Usage:
14+
* - uptime : Display shell uptime in hours, minutes, and seconds
15+
*
16+
* The output format shows the uptime as "Up since Xh Ym Zs" where:
17+
* - X is hours
18+
* - Y is minutes
19+
* - Z is seconds
20+
*
21+
* This is useful for monitoring how long a shell session has been active.
22+
*/
23+
public class UptimeCommand implements Command {
24+
@Override
25+
public void execute(String[] args, ShellContext context) {
26+
long uptimeMillis = System.currentTimeMillis() - context.getStartTime();
27+
28+
long totalSeconds = uptimeMillis / 1000;
29+
long hours = totalSeconds / 3600;
30+
long minutes = (totalSeconds % 3600) / 60;
31+
long seconds = totalSeconds % 60;
32+
33+
System.out.printf("Up since %dh %dm %ds%n", hours, minutes, seconds);
34+
}
35+
36+
@Override
37+
public String description() {
38+
return "Display how long the shell has been running since startup.";
39+
}
40+
41+
@Override
42+
public String usage() {
43+
return "uptime";
44+
}
45+
}

target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst

Whitespace-only changes.

0 commit comments

Comments
 (0)