Skip to content

Commit

Permalink
no more connect_ids; facebook only connects to newly added page(s)
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderGi authored and devxpy committed Aug 19, 2024
1 parent 1119c84 commit e1e376a
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 87 deletions.
84 changes: 38 additions & 46 deletions recipes/VideoBots.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from furl import furl
from pydantic import BaseModel, Field

from bots.models import BotIntegration, Platform
from bots.models import BotIntegration, Platform, SavedRun, PublishedRun
from bots.models import Workflow
from celeryapp.tasks import send_integration_attempt_email
from daras_ai.image_input import (
Expand Down Expand Up @@ -1088,10 +1088,6 @@ def render_integrations_tab(self):
)
return

# if we come from an integration redirect, we connect the integrations
if "connect_ids" in self.request.query_params:
self.integrations_on_connect(current_run, published_run)

# see which integrations are available to the user for the current published run
assert published_run, "At this point, published_run should be available"
integrations_q = Q(published_run=published_run) | Q(
Expand Down Expand Up @@ -1165,24 +1161,27 @@ def render_integrations_add(self, label: str, run_title: str):
gui.caption(choice.label)

if pressed_platform:
on_connect = self.current_app_url(RecipeTabs.integrations)
current_run, published_run = (
self.get_current_sr(),
self.get_current_published_run(),
)
current_run_id, published_run_id = (
current_run.run_id if current_run else None
), (published_run.published_run_id if published_run else None)
match pressed_platform:
case Platform.WEB:
bi = BotIntegration.objects.create(
name=run_title,
billing_account_uid=self.request.user.uid,
platform=Platform.WEB,
)
redirect_url = str(
furl(on_connect).add(query_params=dict(connect_ids=str(bi.id)))
/ bi.api_integration_id()
)
redirect_url = connect(bi, current_run, published_run)
case Platform.WHATSAPP:
redirect_url = wa_connect_url(on_connect)
redirect_url = wa_connect_url(current_run_id, published_run_id)
case Platform.SLACK:
redirect_url = slack_connect_url(on_connect)
redirect_url = slack_connect_url(current_run_id, published_run_id)
case Platform.FACEBOOK:
redirect_url = fb_connect_url(on_connect)
redirect_url = fb_connect_url(current_run_id, published_run_id)
case _:
raise ValueError(f"Unsupported platform: {pressed_platform}")

Expand Down Expand Up @@ -1416,41 +1415,34 @@ def render_integrations_settings(
bi.save()
gui.rerun()

def integrations_on_connect(self, current_run, published_run):
from app_users.models import AppUser
from daras_ai_v2.slack_bot import send_confirmation_msg

bi = None
for bid in self.request.query_params.getlist("connect_ids"):
try:
bi = BotIntegration.objects.get(id=bid)
except BotIntegration.DoesNotExist:
continue
if bi.saved_run is not None:
with gui.center():
gui.write(
f"⚠️ {bi.get_display_name()} is already connected to a different published run by {AppUser.objects.filter(uid=bi.billing_account_uid).first().display_name}. Please disconnect it first."
)
return
def connect(
bi: BotIntegration, current_run: SavedRun, published_run: PublishedRun | None
) -> RedirectException:
"""
Connect the bot integration to the provided saved and published runs.
Returns a redirect exception to the integrations page for that bot integration.
"""

bi.streaming_enabled = True
bi.saved_run = current_run
if published_run and published_run.saved_run_id == current_run.id:
bi.published_run = published_run
else:
bi.published_run = None
if bi.platform == Platform.SLACK:
bi.slack_create_personal_channels = False
send_confirmation_msg(bi)
bi.save()

if bi:
path_params = dict(integration_id=bi.api_integration_id())
else:
path_params = dict()
raise gui.RedirectException(
self.current_app_url(RecipeTabs.integrations, path_params=path_params)
)
from daras_ai_v2.slack_bot import send_confirmation_msg

print(f"Connecting {bi} to {current_run} and {published_run}")

bi.streaming_enabled = True
bi.saved_run = current_run
if published_run and published_run.saved_run.id == current_run.id:
bi.published_run = published_run
else:
bi.published_run = None
if bi.platform == Platform.SLACK:
bi.slack_create_personal_channels = False
send_confirmation_msg(bi)
bi.save()

path_params = dict(integration_id=bi.api_integration_id())
return RedirectException(
VideoBotsPage.current_app_url(RecipeTabs.integrations, path_params=path_params)
)


def messages_as_prompt(query_msgs: list[dict]) -> str:
Expand Down
94 changes: 62 additions & 32 deletions routers/facebook_api.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import requests
from fastapi.responses import RedirectResponse
from furl import furl
import json
from starlette.background import BackgroundTasks
from starlette.requests import Request
from starlette.responses import HTMLResponse, Response

from bots.models import BotIntegration, Platform
from bots.models import BotIntegration, Platform, SavedRun, PublishedRun
from daras_ai_v2 import settings, db
from daras_ai_v2.bots import msg_handler
from daras_ai_v2.exceptions import raise_for_status
from daras_ai_v2.facebook_bots import WhatsappBot, FacebookBot
from daras_ai_v2.fastapi_tricks import fastapi_request_json
from daras_ai_v2.functional import map_parallel
from recipes.VideoBots import connect
from routers.custom_api_router import CustomAPIRouter

app = CustomAPIRouter()
Expand All @@ -23,8 +25,16 @@ def fb_connect_whatsapp_redirect(request: Request):
redirect_url = furl("/login", query_params={"next": request.url})
return RedirectResponse(str(redirect_url))

on_completion = request.query_params.get("state")
retry_button = f'<a href="{wa_connect_url(on_completion)}">Retry</a>'
connection_state = json.loads(request.query_params.get("state", "{}"))
current_run_id = connection_state.get("current_run_id", None)
published_run_id = connection_state.get("published_run_id", None)
retry_button = (
f'<a href="{wa_connect_url(current_run_id, published_run_id)}">Retry</a>'
)
current_run = SavedRun.objects.get(run_id=current_run_id)
published_run = PublishedRun.objects.filter(
published_run_id=published_run_id
).first()

code = request.query_params.get("code")
if not code:
Expand Down Expand Up @@ -64,7 +74,7 @@ def fb_connect_whatsapp_redirect(request: Request):
# {'data': [{'verified_name': 'XXXX', 'code_verification_status': 'VERIFIED', 'display_phone_number': 'XXXX', 'quality_rating': 'UNKNOWN', 'platform_type': 'NOT_APPLICABLE', 'throughput': {'level': 'NOT_APPLICABLE'}, 'last_onboarded_time': '2024-02-22T20:42:16+0000', 'id': 'XXXX'}], 'paging': {'cursors': {'before': 'XXXX', 'after': 'XXXX'}}}
phone_numbers = r.json()["data"]

integrations = []
redirect = None
for phone_number in phone_numbers:
business_name = phone_number["verified_name"]
display_phone_number = phone_number["display_phone_number"]
Expand Down Expand Up @@ -98,7 +108,7 @@ def fb_connect_whatsapp_redirect(request: Request):
)
r.raise_for_status()

# subscript our app to weebhooks for WABA
# subscribe our app to weebhooks for WABA
r = requests.post(
f"https://graph.facebook.com/v19.0/{waba_id}/subscribed_apps?access_token={user_access_token}",
json={
Expand All @@ -110,10 +120,12 @@ def fb_connect_whatsapp_redirect(request: Request):
)
r.raise_for_status()

integrations.append(bi)
redirect = connect(bi, current_run, published_run)

return return_to_app_url(integrations, on_completion) or HTMLResponse(
f"Sucessfully Connected to whatsapp! You may now close this page."
return (
RedirectResponse(url=redirect.url, status_code=redirect.status_code)
if redirect
else HTMLResponse("No phone numbers found!" + retry_button)
)


Expand All @@ -123,8 +135,16 @@ def fb_connect_redirect(request: Request):
redirect_url = furl("/login", query_params={"next": request.url})
return RedirectResponse(str(redirect_url))

on_completion = request.query_params.get("state")
retry_button = f'<a href="{fb_connect_url(on_completion)}">Retry</a>'
connection_state = json.loads(request.query_params.get("state", "{}"))
current_run_id: str | None = connection_state.get("current_run_id", None)
published_run_id: str | None = connection_state.get("published_run_id", None)
retry_button = (
f'<a href="{fb_connect_url(current_run_id, published_run_id)}">Retry</a>'
)
current_run = SavedRun.objects.get(run_id=current_run_id)
published_run = PublishedRun.objects.filter(
published_run_id=published_run_id
).first()

code = request.query_params.get("code")
if not code:
Expand All @@ -146,14 +166,31 @@ def fb_connect_redirect(request: Request):
status_code=400,
)

# only connect to pages that are not already connected
fb_pages = [
fb_page
for fb_page in fb_pages
if BotIntegration.objects.filter(
fb_page_id=fb_page["id"]
) # this will need to change if we ever add instagram
.exclude(saved_run__isnull=True)
.count()
== 0
]

map_parallel(_subscribe_to_page, fb_pages)
integrations = BotIntegration.objects.reset_fb_pages_for_user(
request.user.uid, fb_pages
)

page_names = ", ".join(map(str, integrations))
return return_to_app_url(integrations, on_completion) or HTMLResponse(
f"Sucessfully Connected to {page_names}! You may now close this page."
redirect = None
for integration in integrations:
redirect = connect(integration, current_run, published_run)

return (
RedirectResponse(url=redirect.url, status_code=redirect.status_code)
if redirect
else HTMLResponse("No pages found!" + retry_button)
)


Expand Down Expand Up @@ -221,19 +258,6 @@ def fb_webhook(
return Response("OK")


def return_to_app_url(
integrations: list,
on_completion: str | None = None,
) -> bool | RedirectResponse:
if not on_completion or not integrations:
return False
return RedirectResponse(
furl(on_completion)
.add(query_params={"connect_ids": ",".join([str(i.id) for i in integrations])})
.tostr()
)


wa_connect_redirect_url = (
furl(
settings.APP_BASE_URL,
Expand All @@ -242,7 +266,7 @@ def return_to_app_url(
).tostr()


def wa_connect_url(on_completion: str | None = None) -> str:
def wa_connect_url(current_run_id: str | None, published_run_id: str | None) -> str:
return furl(
"https://www.facebook.com/v18.0/dialog/oauth",
query_params={
Expand All @@ -251,7 +275,9 @@ def wa_connect_url(on_completion: str | None = None) -> str:
"redirect_uri": wa_connect_redirect_url,
"response_type": "code",
"config_id": settings.FB_WHATSAPP_CONFIG_ID,
"state": on_completion,
"state": json.dumps(
dict(current_run_id=current_run_id, published_run_id=published_run_id)
),
},
).tostr()

Expand All @@ -264,7 +290,7 @@ def wa_connect_url(on_completion: str | None = None) -> str:
).tostr()


def fb_connect_url(on_completion: str | None = None) -> str:
def fb_connect_url(current_run_id: str | None, published_run_id: str | None) -> str:
return furl(
"https://www.facebook.com/dialog/oauth",
query_params={
Expand All @@ -279,12 +305,14 @@ def fb_connect_url(on_completion: str | None = None) -> str:
"pages_show_list",
]
),
"state": on_completion,
"state": json.dumps(
dict(current_run_id=current_run_id, published_run_id=published_run_id)
),
},
).tostr()


def ig_connect_url(on_completion: str | None = None) -> str:
def ig_connect_url(current_run_id: str | None, published_run_id: str | None) -> str:
return furl(
"https://www.facebook.com/dialog/oauth",
query_params={
Expand All @@ -302,7 +330,9 @@ def ig_connect_url(on_completion: str | None = None) -> str:
"pages_show_list",
]
),
"state": on_completion,
"state": json.dumps(
dict(current_run_id=current_run_id, published_run_id=published_run_id)
),
},
).tostr()

Expand Down
Loading

0 comments on commit e1e376a

Please sign in to comment.