I am working on a notification app linked to a business account via a webhook to get notified when any of the team members edit files in certain folders. Attached below is the code, deployed on Heroku
import os
from dotenv import load_dotenv
from dropbox import Dropbox
from flask import Flask, render_template, session, Response, request, abort
import hmac
from hashlib import sha256
import json
import threading
import sendgrid
from sendgrid.helpers.mail import *
import redis
from dropbox.files import DeletedMetadata, FolderMetadata, WriteMode, FileMetadata
from dropbox.users import FullAccount
load_dotenv()
ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN')
APP_KEY = os.environ.get('APP_KEY')
APP_SECRET = os.environ.get('APP_SECRET')
EMAIL_USERNAME = os.environ.get('EMAIL_USERNAME')
redis_url = os.environ.get('REDISTOGO_URL')
redis_client = redis.from_url(redis_url, decode_responses=True)
main_folder = 'Career Consulting Real'
subfolder_list = ['eng101', "mat101"]
app = Flask(__name__)
app.secret_key = os.environ.get('FLASK_SECRET_KEY')
@app.route('/')
def index():
return render_template('index.html')
@app.route('/login')
def login():
return render_template('done.html')
@app.route('/webhook', methods=['GET'])
def challenge():
resp = Response(request.args.get('challenge'))
resp.headers['Content-Type'] = 'text/plain'
resp.headers['X-Content-Type-Options'] = 'nosniff'
print(resp)
return resp
@app.route('/webhook', methods=['POST'])
def webhook():
# '''Receive a list of changed user IDs from Dropbox and process each.'''
#make sure this is a valid request from Dropbox
signature = request.headers.get('X-Dropbox-Signature')
key = bytes(APP_SECRET, encoding="ascii")
if not hmac.compare_digest(signature, hmac.new(key, request.data, sha256).hexdigest()):
abort(403)
#print(json.loads(request.data))
#print(json.loads(request.data)['delta']['teams']['dbtid:AAB_JmVTCr29MzCFLUPWLOP3ch-RdRv3Quo'])
for account in json.loads(request.data)['delta']['teams']['dbtid:AAB_JmVTCr29MzCFLUPWLOP3ch-RdRv3Quo']:
# We need to respond quickly to the webhook request, so we do the
# actual work in a separate thread. For more robustness, it's a
# good idea to add the work to a reliable queue and process the queue
# in a worker process.
threading.Thread(target=process_user, args=(account,)).start()
return ''
def filter_notifications(entry):
file_path_split = entry.path_display.replace(' ', '').lower().split('/')
if file_path_split[1] == main_folder.replace(' ', '').lower():
for subfolder in subfolder_list:
if subfolder in file_path_split[2]:
return True
def send_notification(message):
send_grid_key = os.environ.get('SEND_GRID')
sg = sendgrid.SendGridAPIClient(api_key=send_grid_key)
from_email = Email(EMAIL_USERNAME)
to_email = To("cdropboxchanges@gmail.com")
subject = "A change has been made"
content = Content("text/plain", message)
mail = Mail(from_email, to_email, subject, content)
response = sg.client.mail.send.post(request_body=mail.get())
def process_user(account):
# cursor for the user (None the first time)
cursor = redis_client.hget('cursors', account)
dbx = Dropbox(ACCESS_TOKEN)
has_more = True
while has_more:
if cursor is None:
result = dbx.files_list_folder(path='', recursive=True, include_non_downloadable_files=True)
else:
result = dbx.files_list_folder_continue(cursor)
for entry in result.entries:
if filter_notifications(entry):
if isinstance(entry, FileMetadata):
send_notification('File Metadat')
elif isinstance(entry, DeletedMetadata):
send_notification('DeletedMetadata')
elif isinstance(entry, FolderMetadata):
send_notification('Folder Metadata')
else:
send_notification('Something happened, not sure what...')
# Update cursor
cursor = result.cursor
redis_client.hset('cursors', account, cursor)
# Repeat only if there's more to do
has_more = result.has_more
if __name__ == '__main__':
app.run(debug=True)
When I run the code, I get the following error:
dropbox.exceptions.AuthError: AuthError('adf0b24714c641a5b3dfcd68573db5e4', AuthError('invalid_access_token', None))
However, the access token I am passing in is straight from the app on Dropbox.
Can you please advise what could be the problem that is causing this error?
Thank you