Skip to content

Commit ab2e256

Browse files
Merge pull request #77 from yasht01/custom-api-key
Add feature to setup custom API key #77
2 parents 8953712 + 5d8f713 commit ab2e256

File tree

5 files changed

+91
-1
lines changed

5 files changed

+91
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Options: <br>
4444
`-v, --version -> Gives the Version of the CLI` <br>
4545
`-s, --search -> Search a question on Stackoverflow` <br>
4646
`-d, --debug -> Turn on Debugging mode` <br>
47+
`-c, --custom -> Setup a custom API key` <br>
4748
`-h, --help -> Shows this message and exit` <br>
4849

4950
## License🗄

main.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636
help="Save answer to a file",
3737
action="store_true")
3838

39+
parser.add_argument("-c",
40+
"--custom",
41+
help="Set a custom API key",
42+
action="store_true")
43+
3944
parser.add_argument("-u",
4045
"--update",
4146
help="Check updates for the application",

requirements.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ requests==2.24.0
55
termcolor==1.1.0
66
urllib3==1.25.10
77
rich==9.9.0
8+
oauthlib==3.1.0
9+
requests-oauthlib==1.3.0
10+
colorama==0.4.4
11+
configparser==5.0.2
12+
crayons==0.4.0
13+
selenium==3.141.0
14+
webdriver-manager==3.3.0

src/arguments/search.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ def search_args(self):
4040
webbrowser.open(f"{url}?title={self.arguments.new}")
4141
else:
4242
webbrowser.open(url)
43+
elif self.arguments.custom:
44+
self.utility_object.setCustomKey()
4345
elif self.arguments.update:
4446
update = UpdateApplication(version)
4547
update.check_for_updates()

src/arguments/utility.py

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@
77
from .save import SaveSearchResults
88
from .markdown import MarkdownRenderer
99

10+
# Required for OAuth
11+
import json
12+
from oauthlib.oauth2 import MobileApplicationClient
13+
from requests_oauthlib import OAuth2Session
14+
15+
# Required for Selenium script and for web_driver_manager
16+
import time
17+
from selenium import webdriver
18+
from selenium.webdriver.common.by import By
19+
from selenium.webdriver.support.ui import WebDriverWait
20+
from selenium.webdriver.support import expected_conditions as EC
21+
22+
from webdriver_manager.chrome import ChromeDriverManager
23+
from webdriver_manager.firefox import GeckoDriverManager
24+
from webdriver_manager.microsoft import EdgeChromiumDriverManager
25+
1026
console = Console()
1127

1228

@@ -85,4 +101,63 @@ def get_ans(self, questions_list):
85101

86102
console.print(output_text)
87103
ans.append(json_ans_data["items"])
88-
return ans
104+
return ans
105+
106+
# Get an access token and extract to a JSON file "access_token.json"
107+
@classmethod
108+
def setCustomKey(self):
109+
client_id = 20013
110+
111+
# scopes possible values:
112+
# read_inbox - access a user's global inbox
113+
# no_expiry - access_token's with this scope do not expire
114+
# write_access - perform write operations as a user
115+
# private_info - access full history of a user's private actions on the site
116+
scopes = 'read_inbox'
117+
118+
authorization_url = 'https://stackoverflow.com/oauth/dialog'
119+
redirect_uri = 'https://stackexchange.com/oauth/login_success'
120+
121+
# Create an OAuth session and open the auth_url in a browser for the user to authenticate
122+
stackApps = OAuth2Session(client=MobileApplicationClient(client_id=client_id), scope=scopes, redirect_uri=redirect_uri)
123+
auth_url, state = stackApps.authorization_url(authorization_url)
124+
125+
# Try to install web drivers for one of these browsers
126+
# Chrome, Firefox, Edge (One of them must be installed)
127+
try:
128+
driver = webdriver.Chrome(ChromeDriverManager().install())
129+
except ValueError:
130+
try:
131+
driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())
132+
except ValueError:
133+
try:
134+
driver = webdriver.Edge(EdgeChromiumDriverManager().install())
135+
except ValueError:
136+
print("You do not have one of these supported browsers: Chrome, Firefox, Edge")
137+
138+
# Open auth_url in one of the supported browsers
139+
driver.get(auth_url)
140+
141+
# Close the window after 20s (Assuming that the user logs in within 30 seconds)
142+
time.sleep(30)
143+
# Close the windows as soon as authorization is done
144+
try:
145+
WebDriverWait(driver, 1).until(
146+
EC.presence_of_element_located((By.TAG_NAME, "h2"))
147+
)
148+
callback_url = driver.current_url
149+
finally:
150+
driver.quit()
151+
152+
# Extract access token data from callback_url
153+
accessTokenData = stackApps.token_from_fragment(callback_url)
154+
155+
# Store the access token data in a dictionary
156+
jsonDict = {
157+
"access_token": accessTokenData['access_token'],
158+
"expires": accessTokenData['expires'],
159+
"state": state
160+
}
161+
162+
with open('access_token.json', 'w') as jsonFile:
163+
json.dump(jsonDict, jsonFile)

0 commit comments

Comments
 (0)