Skip to content

Commit 7d6716f

Browse files
committed
Add language and keyword filters to search command
1 parent b68e5bd commit 7d6716f

1 file changed

Lines changed: 231 additions & 0 deletions

File tree

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
import sys
2+
from typing import Iterable, List, Optional, Union
3+
4+
import click
5+
from halo import Halo
6+
from rich.console import Console
7+
from tabulate import tabulate
8+
9+
from good_first_issues import utils
10+
from good_first_issues.graphql import services
11+
from good_first_issues.utils import ParsedDuration, parse_period
12+
13+
console = Console(color_system="auto")
14+
15+
16+
period_help_msg = """
17+
Specify a time range for filtering data.
18+
Converts the specified time range to UTC date time.
19+
20+
# Query all organization repos
21+
$ gfi search "rust-lang" --period "30 hours"
22+
23+
# Query a specific repo in an organization
24+
$ gfi search "rust-lang" --repo "rust" -p "30 mins"
25+
26+
# Query repos with the topic hacktoberfest
27+
$ gfi search -hf -p "100 days"
28+
29+
# Query all user repos
30+
$ gfi search "yankeexe" --user -p "600 hrs"
31+
32+
# Query a specific repo of a user
33+
$ gfi search "yankeexe" --user --repo "good-first-issues" -p "600 days"
34+
35+
--period 1 m,min,mins,minutes
36+
--period 2 h,hr,hour,hours,hrs
37+
--period 3 d,day,days
38+
"""
39+
40+
41+
@click.command()
42+
@click.option(
43+
"--repo",
44+
"-r",
45+
help="Search in a specific repo of user or organization",
46+
type=str,
47+
)
48+
@click.option(
49+
"--hacktoberfest",
50+
"-hf",
51+
help="Search repositories with topic hacktoberfest",
52+
is_flag=True,
53+
)
54+
@click.option(
55+
"--limit",
56+
"-l",
57+
help="Limit the number of issues to display. Defaults to 10",
58+
type=int,
59+
default=10,
60+
)
61+
@click.option(
62+
"--user",
63+
"-u",
64+
help="Specify if it's a user repository",
65+
is_flag=True,
66+
)
67+
@click.option(
68+
"--web",
69+
help="Display issues on browser",
70+
is_flag=True,
71+
)
72+
@click.option(
73+
"--all",
74+
"-a",
75+
help="View all the issues found without limits.",
76+
is_flag=True,
77+
)
78+
@click.option("--period", "-p", help=period_help_msg)
79+
@click.option(
80+
"--language",
81+
"-lang",
82+
help="Filter issues by programming language (e.g., Python, JavaScript)",
83+
type=str,
84+
default=None,
85+
)
86+
@click.option(
87+
"--keyword",
88+
"-k",
89+
help="Filter issues by keyword in title or description",
90+
type=str,
91+
default=None,
92+
)
93+
@click.argument("name", required=False)
94+
def search(
95+
name: str,
96+
repo: str,
97+
user: bool,
98+
web: bool,
99+
limit: int,
100+
all: bool,
101+
hacktoberfest: bool,
102+
period: str,
103+
language: str,
104+
keyword: str,
105+
):
106+
"""Search for good first issues in organizations or user repositories.
107+
108+
Usage:
109+
110+
gfi search <repo-owner/org-name>
111+
112+
➡️ repo owner
113+
gfi search "yankeexe" --user
114+
115+
➡️ org name
116+
gfi search "ollama"
117+
118+
➡️ search in a particular repo
119+
gfi search "yankeexe" --repo "good-first-issues"
120+
gfi search "ollama" --repo "ollama-python"
121+
122+
➡️ filter by language
123+
gfi search "facebook" --language "Python"
124+
125+
➡️ filter by keyword
126+
gfi search "rust-lang" --keyword "documentation"
127+
128+
➡️ combine filters
129+
gfi search "microsoft" --language "JavaScript" --keyword "API"
130+
"""
131+
132+
if name is None and hacktoberfest is False:
133+
utils.print_help_msg(search)
134+
sys.exit()
135+
136+
issues: Optional[Iterable] = None
137+
rate_limit: int = 0
138+
139+
# Check for GitHub Token
140+
token: Union[str, bool] = utils.check_credential()
141+
142+
if period:
143+
period: ParsedDuration = parse_period(period)
144+
period = period.utc_date_time.strftime("%Y-%m-%dT%H:%M:%SZ")
145+
146+
# Identify the flags passed.
147+
query, variables, mode = services.identify_mode(
148+
name, repo, user, hacktoberfest, period, limit
149+
)
150+
151+
# Spinner
152+
spinner = Halo(text="Fetching repos...", spinner="dots")
153+
spinner.start()
154+
155+
# API Call
156+
response = services.caller(token, query, variables)
157+
spinner.succeed("Repos fetched.")
158+
159+
# Data Filtering
160+
if mode in ["org", "user"]:
161+
issues, rate_limit = services.org_user_pipeline(response, mode)
162+
163+
if mode == "repo":
164+
issues, rate_limit = services.org_user_pipeline(response, mode)
165+
166+
if mode == "search":
167+
issues, rate_limit = services.extract_search_results(response)
168+
issues = issues[:limit] # cannot set limit on the search_query directly
169+
170+
# Apply keyword filter
171+
if keyword:
172+
filtered_issues = []
173+
for issue in issues:
174+
title = issue[0].lower()
175+
if keyword.lower() in title:
176+
filtered_issues.append(issue)
177+
issues = filtered_issues
178+
179+
# Apply language filter
180+
if language:
181+
filtered_issues = []
182+
for issue in issues:
183+
title = issue[0].lower()
184+
if language.lower() in title:
185+
filtered_issues.append(issue)
186+
issues = filtered_issues
187+
188+
table_headers: List = ["Title", "Issue URL"]
189+
190+
# No good first issues found
191+
if not issues:
192+
console.print(
193+
f"Remaining requests:dash:: {rate_limit}",
194+
style="bold green",
195+
)
196+
return console.print(
197+
"No good first issues found!:mask:",
198+
style="bold red",
199+
)
200+
201+
# Display issues in browser
202+
if web:
203+
html_data = tabulate(issues, table_headers, tablefmt="html")
204+
return utils.web_server(html_data)
205+
206+
# Display issues in terminal
207+
row_ids = list(range(1, len(issues) + 1))
208+
print(
209+
tabulate(
210+
issues,
211+
table_headers,
212+
tablefmt="fancy_grid",
213+
showindex=row_ids,
214+
)
215+
)
216+
217+
console.print(f"Remaining requests:dash:: {rate_limit}", style="bold green")
218+
219+
# Show applied filters
220+
if keyword or language:
221+
filter_info = []
222+
if language:
223+
filter_info.append(f"language: {language}")
224+
if keyword:
225+
filter_info.append(f"keyword: {keyword}")
226+
console.print(
227+
f"Filters applied: {', '.join(filter_info)}",
228+
style="bold cyan",
229+
)
230+
231+
console.print("Happy Hacking :tada::zap::rocket:", style="bold blue")

0 commit comments

Comments
 (0)