Skip to content

Commit

Permalink
add quickstart cog
Browse files Browse the repository at this point in the history
  • Loading branch information
jsmsj committed Aug 5, 2022
1 parent a8ecfb3 commit ed985dc
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 26 deletions.
5 changes: 4 additions & 1 deletion TODO
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ make help cmd
make readme
improve oauth flow, preferably netlifyapp
errors :(
make tutorial
make tutorial
drive selector
bypasser
size cmd
13 changes: 12 additions & 1 deletion cogs/_db_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def find_sa_info_by_id(id):

###################################

def create_db_inset_sas(project_id):
def create_db_insert_sas(project_id):
temp = db[f'sas_{project_id}']
sas_folder = 'accounts'
sa_files = os.listdir(sas_folder)
Expand Down Expand Up @@ -155,4 +155,15 @@ async def predicate(ctx:commands.Context):
def has_sa_creds():
async def predicate(ctx:commands.Context):
return True if sascre_find_creds(ctx.author.id) else False
return commands.check(predicate)


def not_has_credentials():
async def predicate(ctx:commands.Context):
return False if find_creds(ctx.author.id) else True
return commands.check(predicate)

def not_has_sa_creds():
async def predicate(ctx:commands.Context):
return False if sascre_find_creds(ctx.author.id) else True
return commands.check(predicate)
8 changes: 6 additions & 2 deletions cogs/_gd_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ def getFilesByFolderId(self, folder_id):
@retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(15),
retry=retry_if_exception_type(HttpError))
def copyFile(self, file_id, dest_id):
body = {'parents': [dest_id]}
body = {
'parents': [dest_id],
'description': 'Uploaded by Gdrive Clone Bot'
}
try:
res = self.__service.files().copy(supportsAllDrives=True,fileId=file_id,body=body).execute()
return res
Expand Down Expand Up @@ -114,7 +117,8 @@ def create_directory(self, directory_name,**kwargs):
parent_id = self.__parent_id
file_metadata = {
"name": directory_name,
"mimeType": self.__G_DRIVE_DIR_MIME_TYPE
"mimeType": self.__G_DRIVE_DIR_MIME_TYPE,
'description': 'Uploaded by Gdrive Clone Bot'
}
file_metadata["parents"] = [parent_id]
file = self.__service.files().create(supportsTeamDrives=True, body=file_metadata).execute()
Expand Down
2 changes: 1 addition & 1 deletion cogs/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def show_progress_still(current:int,total:int,width:int):
def status_emb(transferred:int,current_file_name,total_size:int):
em = discord.Embed(title="📺 Status",color=discord.Color.green(),url="https://github.com/jsmsj/gdriveclonebot")
em.set_footer(text="Made with 💖 by jsmsj")
em.description = f"Name: `{current_file_name}`\nStatus: Copying...📚\nCopied: {humanbytes(transferred)} of {humanbytes(total_size)}\n\n{show_progress_still(transferred,total_size,20)}🏁 {round(transferred*100/total_size,3)} %"
em.description = f"Current File: `{current_file_name}`\nStatus: Copying...📚\nCopied: {humanbytes(transferred)} of {humanbytes(total_size)}\n\n{show_progress_still(transferred,total_size,20)}🏁 {round(transferred*100/total_size,3)} %"
return em

def zip_sas_cre():
Expand Down
4 changes: 2 additions & 2 deletions cogs/_sa_creation_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ def _list_sas(iam,project):
class ServAcc:
def __init__(self,user_id):
self.user_id = user_id
self.scopes = ['https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/cloud-platform','https://www.googleapis.com/auth/iam']
self.scopes = ['https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/cloud-platform','https://www.googleapis.com/auth/iam','https://www.googleapis.com/auth/service.management']
self.sleep_time = 30
self.creds = db.sascre_find_creds(self.user_id)
self._services = self.authorise()
self.services=['iam','drive']
self.services=['iam','drive','serviceusage','cloudresourcemanager']
self.current_key_dump = []

def authorise(self):
Expand Down
87 changes: 87 additions & 0 deletions cogs/quickstart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""Imports"""
import json
import shutil

import discord
from discord.ext import commands
from main import logger

import cogs._db_helpers as db
import cogs._sa_creation_utils as sascre
from cogs._db_helpers import not_has_sa_creds,not_has_credentials
from cogs._helpers import embed, is_allowed, zip_sas_cre
import os


class Quickstart(commands.Cog):
"""Quickstart commands"""

def __init__(self, bot):
self.bot = bot

async def cog_before_invoke(self, ctx):
"""
Triggers typing indicator on Discord before every command.
"""
await ctx.trigger_typing()
return

@is_allowed()
@not_has_credentials()
@not_has_sa_creds()
@commands.command()
async def makeithappen(self,ctx:commands.Context,projectid=None,link=None):
if not projectid:
return await ctx.send("Error: No project id found, correct usage `gcb quickstart projectid link`.")
if not link:
return await ctx.send("Error: No folder id found, correct usage `gcb quickstart projectid link`.")
await ctx.invoke(self.bot.get_command('authsa'))
await ctx.invoke(self.bot.get_command('auth'))
await ctx.invoke(self.bot.get_command('createsa'), projectid=projectid)
try:
sa_cls = sascre.ServAcc(ctx.author.id)
msg = await ctx.send(embed=embed(title="🧾 Service Accounts",description="Downloading the accounts, please wait ...")[0])
if db.sas_for_projid_exists(projectid):
db.download_sas_projid(projectid)
else:
sa_cls.download_keys(projectid)
db.create_db_insert_sas(projectid)
zip_sas_cre()
await msg.edit(embed=embed("🧾 Service Accounts","Here is the zip file for your service accounts.")[0])
await ctx.send(file=discord.File('aaccounts.zip'))
list_of_acc_fname = os.listdir('accounts')
with open('emails.txt','a') as f:
for i in list_of_acc_fname:
with open(f'accounts/{i}') as f2:
data = json.load(f2)
f.write(data["client_email"]+"\n")
await ctx.send(embed=embed("🧾 Service Accounts","Here is the emails file. Add these to a google group and add that google group to a teamdrive, incase you want to copy stuff to teamdrive.")[0],file=discord.File('emails.txt'))
for idx,filename in enumerate(list_of_acc_fname):
with open('accounts'+f"\\{filename}") as f:
data = json.load(f)
data['sa_file_index'] = idx
db.sas_db.insert_one(data)

em,view = embed("🧾 Service Accounts","Added Service Accounts successfully.",None)
await ctx.send(embed=em,view=view)
except Exception as e:
logger.warning(e)
finally:
if os.path.exists('aaccounts.zip'):
os.remove('aaccounts.zip')
if os.path.exists('accounts'):
shutil.rmtree('accounts')
if os.path.exists('emails.txt'):
os.remove('emails.txt')

await ctx.invoke(self.bot.get_command('set_folder'),link=link)
em = embed("🎌 Congratulations","Setup done successfully, now you can clone public as well as private links!\nCommands:\n`gcb pubclone drive.google.com/XXXXXXXX`\n`gcb privclone drive.google.com/XXXXXXXX`\nTo get help on above commands run `gcb help cmd_name`",None)[0]
await ctx.send(embed=em)

@makeithappen.error
async def make_it_happn_err(self,ctx,error):
return await ctx.send("You have already ran this command once. It cannot be run again. Use other avaialbe commands to generate Service Accounts.")

def setup(bot):
bot.add_cog(Quickstart(bot))
print("Quickstart cog is loaded")
49 changes: 30 additions & 19 deletions cogs/serviceaccs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Imports"""
import urllib
import requests
import os,shutil

import discord
Expand Down Expand Up @@ -52,39 +53,33 @@ async def authsa(self,ctx):
}
}
flow = InstalledAppFlow.from_client_config(credentials,sascre.SCOPES)
flow.redirect_uri = 'https://jsmsj.github.io/GdriveCloneBot/auth'
auth_url, _ = flow.authorization_url()
# em,view = embed(title="🧾 Service Accounts",description=f"Visit the following URL and the authorise. You will be redirected to a error page. That page's url would be something like: https://localhost:1/XXXXXXXXX\nCopy that url and send here within 2 minutes.\n\n{auth_url}",url=auth_url)
em,view = embed(title="🧾 Service Accounts",description=f"Visit the following URL and the authorise. Make sure to select all the scopes, copy the code and send it here within 2 minutes.\n\n{auth_url}",url=auth_url)
# flow.redirect_uri = 'https://jsmsj.github.io/GdriveCloneBot/auth'
flow.redirect_uri = 'http://localhost:1'
auth_url, _ = flow.authorization_url(access_type='offline')
em,view = embed(title="🧾 Service Accounts",description=f"Visit the following URL and the authorise. You will be redirected to a error page. That page's url would be something like: https://localhost:1/XXXXXXXXX\nCopy that url and send here within 2 minutes.\n\n{auth_url}",url=auth_url)
# em,view = embed(title="🧾 Service Accounts",description=f"Visit the following URL and the authorise. Make sure to select all the scopes, copy the code and send it here within 2 minutes.\n\n{auth_url}",url=auth_url)
await ctx.send(embed=em,view=view)
msg:discord.Message = await self.bot.wait_for('message', check=lambda message : message.author == ctx.author and message.channel == ctx.channel, timeout=120)
sent_message = await ctx.reply("🕵️**Checking the received code...**")
try:
redir_url = msg.content
# query = urllib.parse.urlparse(redir_url).query
# code = urllib.parse.parse_qs(query)['code'][0]
code = redir_url
query = urllib.parse.urlparse(redir_url).query
code = urllib.parse.parse_qs(query)['code'][0]
# code = redir_url
flow.fetch_token(code=code)
creds = flow.credentials
db.sascre_insert_creds(ctx.author.id,creds)
em = embed(title="🧾 Service Accounts",description="You have successfully authorized for Service Accounts")[0]
await sent_message.edit(embed=em)
except Exception as e:
logger.warning(e)
# em,view = embed(title='❗ Invalid Link',description='The link you have sent is invalid. Generate new one by the Authorization URL',url=auth_url)
em,view = embed(title='❗ Invalid Code',description='The code you sent is invalid. Generate new one by the Authorization URL',url=auth_url)
em,view = embed(title='❗ Invalid Link',description='The link you have sent is invalid. Generate new one by the Authorization URL `gcb authsa`',url=auth_url)
# em,view = embed(title='❗ Invalid Code',description='The code you sent is invalid. Generate new one by the Authorization URL',url=auth_url)
await sent_message.edit(embed=em,view=view)
else:
em = embed(title="🧾 Service Accounts",description="You have already authorized for Service Accounts")[0]
await ctx.send(embed=em)

@is_allowed()
@commands.command()
async def revokesa(self,ctx):
db.sascre_delete_creds(ctx.author.id)
em = embed(f"🔓 Revoked current logged in account for Service Accounts successfully.","Use `gcb authsa` to authenticate again for service accounts.",None)[0]
await ctx.send(embed=em)

@has_sa_creds()
@is_allowed()
@commands.command()
Expand Down Expand Up @@ -121,7 +116,7 @@ async def downloadsazip(self,ctx,projectid=None):
db.download_sas_projid(projectid)
else:
sa_cls.download_keys(projectid)
db.create_db_inset_sas(projectid)
db.create_db_insert_sas(projectid)
zip_sas_cre()
await msg.edit(embed=embed("🧾 Service Accounts","Here is the zip file for your service accounts.")[0],file=discord.File('aaccounts.zip'))
except Exception as e:
Expand All @@ -145,7 +140,7 @@ async def saemails(self,ctx,projectid=None):
db.download_sas_projid(projectid)
else:
sa_cls.download_keys(projectid)
db.create_db_inset_sas(projectid)
db.create_db_insert_sas(projectid)
list_of_acc_fname = os.listdir('accounts')
with open('emails.txt','a') as f:
for i in list_of_acc_fname:
Expand All @@ -161,7 +156,23 @@ async def saemails(self,ctx,projectid=None):
if os.path.exists('emails.txt'):
os.remove('emails.txt')


@has_sa_creds()
@is_allowed()
@commands.command()
async def revokesa(self,ctx):
creds = db.sascre_find_creds(ctx.author.id)
if creds:
revoke = requests.post('https://accounts.google.com/o/oauth2/revoke',
params={'token': creds.token},
headers = {'content-type': 'application/x-www-form-urlencoded'})
if revoke.status_code == 200:
db.sascre_delete_creds(ctx.author.id)
await ctx.send(embed=embed("🔓 Revoked current logged in account for Service Accounts.","Use `gcb authsa` to authenticate again.",None)[0])
else:
await ctx.send(embed=embed("❗ Error | Unable to delete credentials",f"An error occured\nError: {revoke.json()['error']}\nDescription: {revoke.json()['error_description']}",None)[0])
else:
await ctx.send(embed=embed("🔓 Already Revoked","You haven't even signed in. Use `gcb authsa` to sign in.",None)[0])

def setup(bot):
bot.add_cog(ServiceAccounts(bot))
print("ServiceAccounts cog is loaded")
24 changes: 24 additions & 0 deletions docs/auth.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
<!-- Hi guys, I am trying to authorize using my credentials (Desktop app) for a project in python. i am hosting it on heroku. and i want to authorize the user for their google drive, so first of all i want to authorise the user via Oauth2,
```py
flow = InstalledAppFlow.from_client_config(credentials,SCOPES)
# flow.redirect_uri = 'https://mycustomuri.io/auth'
flow.redirect_uri = 'http://localhost:1'
auth_url, _ = flow.authorization_url(access_type='offline')
send_redir_url(author_id)
redir_url = get_redir_url_from_author(author_id)
query = urllib.parse.urlparse(redir_url).query
code = urllib.parse.parse_qs(query)['code'][0]
flow.fetch_token(code=code)
```
so i want to use my custom redirect uri, but it gives me an error, i think it is related to the image attached, that is i cannot use a desktop app for custom redirect uris, and so i will need to have the app run locally through a webserver.
i could go on creating web credentials (custom uri works in that case) but the scopes which i have chosen are not supported over web type application
the current workaround i have as you can see above in the code is that i send the author auth url with redirect as localhost:1 which is surely going to fail at the point google tries to redirect to that, then i ask user for the url they got the error on. for example it would look something like this:
`http://localhost:1/?state=XXXXXXXXXXXXXXXXX&code=4/ALPHANUMERICCODE&scope=https://www.googleapis.com/auth/drive%20https://www.googleapis.com/auth/iam%20https://www.googleapis.com/auth/cloud-platform`
then i use urllib module in python to extract the code `4/ALPHANUMERICCODE`
and then i do flow.fetch_token(code)
but i do not want the use this as it does not look good in production.
Q Is there any way to authorise via custom uri for desktop app ? -->
<!DOCTYPE html>
<html lang="en">
<head>
Expand Down

0 comments on commit ed985dc

Please sign in to comment.