Created
November 15, 2025 02:55
-
-
Save atomkirk/9ca4b78cc30cedd6c55f9a086ab22b25 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule Integrator.Scheduler do | |
| use Oban.Worker, queue: :events, max_attempts: 5 | |
| require Logger | |
| import Ecto.Query | |
| require Logger | |
| alias Integrator.Intercom | |
| alias Integrator.Notion | |
| alias Integrator.UserMatcher | |
| alias Integrator.Slack | |
| alias Integrator.TicketGenerator | |
| alias Integrator.Slugify | |
| alias Integrator.TicketMatcher | |
| alias Integrator.SlackChannel | |
| alias Integrator.Tickets | |
| alias Phoenix.PubSub | |
| alias Integrator.Scheduler | |
| alias Oban.Job | |
| def schedule_next_task(args) do | |
| args | |
| |> Oban.Job.new(worker: __MODULE__, schedule_in: 5) | |
| |> Oban.insert() | |
| end | |
| @impl Oban.Worker | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "fetch_intercom_conversations", | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_texts(conversation_id, intercom_token) do | |
| {:ok, texts} -> | |
| Logger.info("Fetched texts for conversation #{conversation_id}") | |
| schedule_next_task(%{ | |
| "task" => "fetch_slack_messages", | |
| "conversations" => texts, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch texts for conversation #{conversation_id}") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "fetch_slack_messages", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Notion.get_all(notion_token, notion_database_id) do | |
| {:ok, %{tickets: tickets_in_notion, has_more: _has_more}} -> | |
| Logger.info("Fetched tickets from Notion") | |
| schedule_next_task(%{ | |
| "task" => "fetch_notion_tickets", | |
| "conversations" => conversations, | |
| "tickets_in_notion" => tickets_in_notion, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch tickets from Notion") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "fetch_notion_tickets", | |
| "conversations" => conversations, | |
| "tickets_in_notion" => tickets_in_notion, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.get_all_channels(slack_token) do | |
| {:ok, channels} -> | |
| Logger.info("Fetched channels from Slack") | |
| Scheduler.schedule_next_task(%{ | |
| "task" => "find_matching_tickets", | |
| "conversations" => conversations, | |
| "tickets_in_notion" => tickets_in_notion, | |
| "slack_channels" => channels, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch channels from Slack") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "find_matching_tickets", | |
| "conversations" => conversations, | |
| "tickets_in_notion" => tickets_in_notion, | |
| "slack_channels" => slack_channels, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case IO.inspect( | |
| TicketMatcher.find_matching_ticket(conversations, tickets_in_notion, slack_channels) | |
| ) do | |
| {:ok, %{ticket: nil, channel: nil}} -> | |
| Logger.info("Matched tickets no ticket or channel") | |
| Scheduler.schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| {:ok, %{ticket: ticket, channel: nil}} -> | |
| Logger.info("Matched tickets with ticket") | |
| Scheduler.schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| {:ok, %{ticket: nil, channel: channel}} -> | |
| Logger.info("Matched tickets with channel") | |
| Scheduler.schedule_next_task(%{ | |
| "task" => "create_ticket_and_update_channel", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| {:ok, %{ticket: ticket, channel: channel}} -> | |
| Logger.info("Matched tickets with channel and ticket") | |
| Scheduler.schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| {:error, "No content was found in the conversation."} -> | |
| :ok | |
| _ -> | |
| Logger.error("Failed to match tickets") | |
| {:snooze, 5} | |
| end | |
| end | |
| ## FIRST ACTION | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case TicketGenerator.generate_ticket_info(conversations) do | |
| {:ok, ticket_info} -> | |
| Logger.info("Generated ticket info") | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_get_conversation_url", | |
| "ticket_info" => ticket_info, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to generate ticket info") | |
| {:snooze, 5} | |
| end | |
| end | |
| # New separate function to get the conversation URL | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_get_conversation_url", | |
| "ticket_info" => ticket_info, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_conversation_url(conversation_id, intercom_token) do | |
| {:ok, conversation_url} -> | |
| Logger.info("Retrieved Intercom conversation URL") | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_notion_ticket", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to retrieve Intercom conversation URL") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_notion_ticket", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Notion.create_ticket( | |
| ticket_info["title"], | |
| ticket_info["summary"], | |
| conversation_url, | |
| notion_token, | |
| notion_database_id | |
| ) do | |
| {:ok, body} -> | |
| notion_url = body["url"] | |
| notion_page_id = body["id"] | |
| id_with_jmp = | |
| body["properties"]["ID"]["unique_id"]["prefix"] <> | |
| "-" <> | |
| Integer.to_string(body["properties"]["ID"]["unique_id"]["number"]) | |
| slug_for_title = Slugify.make_slug(ticket_info["title"]) | |
| title_for_slack = id_with_jmp <> "-" <> slug_for_title | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Ticket created in Notion") | |
| :ok | |
| _ -> | |
| Logger.error("Failed to create ticket in Notion") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.create_project_channel(title_for_slack, notion_url, slack_token) do | |
| {:ok, channel_id, channel_url} -> | |
| Logger.info("Channel created in Slack") | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_fetch_intercom_admins", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| {:error, "name_taken"} -> | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack <> "New", | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to create channel in Slack") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_fetch_intercom_admins", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_conversation_admins(conversation_id, intercom_token) do | |
| {:ok, intercom_admins} -> | |
| Logger.info("Fetched admins from Intercom") | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_fetch_slack_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch admins from Intercom") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_fetch_slack_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.get_users(slack_token) do | |
| {:ok, slack_users} -> | |
| {_status, best_matches} = | |
| UserMatcher.get_best_matches_for_adding_to_slack(intercom_admins, slack_users) | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_ticket", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => intercom_admins, | |
| "slack_users" => slack_users, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Fetched users from Slack") | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch users from Slack") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_ticket", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => intercom_admins, | |
| "slack_users" => slack_users, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.invite_users_to_channel(channel_id, best_matches, slack_token) do | |
| {:ok, _} -> | |
| Logger.info("Invited users to channel") | |
| schedule_next_task(%{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_ticket_update_slack", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => intercom_admins, | |
| "slack_users" => slack_users, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| {:error, | |
| %{ | |
| "error" => "already_in_channel", | |
| "errors" => [ | |
| %{"error" => "already_in_channel", "ok" => false, "user" => _} | |
| ], | |
| "ok" => false | |
| }} -> | |
| Logger.info("Users already in channel") | |
| Tickets.create_ticket(%{ | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "notion_ticket_name" => ticket_info["title"], | |
| "notion_children" => ticket_info["summary"], | |
| "slack_channel_name" => title_for_slack, | |
| "intercom_conversation_url" => conversation_url, | |
| "intercom_conversation_id" => Integer.to_string(conversation_id), | |
| "slack_channel_url" => channel_url, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Ticket created in Database") | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to invite users to channel") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_notion_ticket_and_slack_channel_task_create_ticket_update_slack", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "id_with_jmp" => _id_with_jmp, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => _channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => _intercom_admins, | |
| "slack_users" => _slack_users, | |
| "best_matches" => _best_matches, | |
| "slack_token" => _slack_token, | |
| "intercom_token" => _intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => _notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Notion.edit_slack_channel(notion_page_id, channel_url, notion_token) do | |
| {:ok, _} -> | |
| Logger.info("Notion ticket updated with Slack channel link") | |
| Tickets.create_ticket(%{ | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "notion_ticket_name" => ticket_info["title"], | |
| "notion_children" => ticket_info["summary"], | |
| "slack_channel_name" => title_for_slack, | |
| "intercom_conversation_url" => conversation_url, | |
| "intercom_conversation_id" => Integer.to_string(conversation_id), | |
| "slack_channel_url" => channel_url, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Ticket created in Database") | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to invite users to channel") | |
| {:snooze, 5} | |
| end | |
| end | |
| ## SECOND ACTION | |
| # First function in the sequence | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_channel_and_update_ticket", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case TicketGenerator.generate_ticket_info(conversations) do | |
| {:ok, ticket_info} -> | |
| notion_page_id = ticket["id"] | |
| notion_url = ticket["url"] | |
| Logger.info("Generated ticket info for existing ticket") | |
| schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket_task_get_conversation_url", | |
| "ticket_info" => ticket_info, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to generate ticket info") | |
| {:snooze, 5} | |
| end | |
| end | |
| # New separate function to get the conversation URL | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_channel_and_update_ticket_task_get_conversation_url", | |
| "ticket_info" => ticket_info, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_conversation_url(conversation_id, intercom_token) do | |
| {:ok, conversation_url} -> | |
| Logger.info("Retrieved Intercom conversation URL") | |
| schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket_task_get_notion_page", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to retrieve Intercom conversation URL") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Function to get the Notion page details | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_channel_and_update_ticket_task_get_notion_page", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => _notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Notion.get_page(notion_page_id, notion_token) do | |
| {:ok, body} -> | |
| id_with_jmp = | |
| body["properties"]["ID"]["unique_id"]["prefix"] <> | |
| "-" <> | |
| Integer.to_string(body["properties"]["ID"]["unique_id"]["number"]) | |
| slug_for_title = Slugify.make_slug(ticket_info["title"]) | |
| title_for_slack = id_with_jmp <> "-" <> slug_for_title | |
| Logger.info("Retrieved Notion page details") | |
| schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket_task_create_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => body["url"], | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to retrieve Notion page") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Next function in the sequence | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_channel_and_update_ticket_task_create_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.create_project_channel(title_for_slack, notion_url, slack_token) do | |
| {:ok, channel_id, channel_url} -> | |
| Logger.info("Channel created in Slack") | |
| schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket_task_fetch_intercom_admins", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| {:error, "name_taken"} -> | |
| schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket_task_create_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack <> "New", | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to create channel in Slack") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Next function | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_channel_and_update_ticket_task_fetch_intercom_admins", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_conversation_admins(conversation_id, intercom_token) do | |
| {:ok, intercom_admins} -> | |
| Logger.info("Fetched admins from Intercom") | |
| schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket_task_fetch_slack_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch admins from Intercom") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Next function | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_channel_and_update_ticket_task_fetch_slack_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.get_users(slack_token) do | |
| {:ok, slack_users} -> | |
| {_status, best_matches} = | |
| UserMatcher.get_best_matches_for_adding_to_slack(intercom_admins, slack_users) | |
| schedule_next_task(%{ | |
| "task" => "create_channel_and_update_ticket_task_finish", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Fetched users from Slack") | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch users from Slack") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Final function in the sequence | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_channel_and_update_ticket_task_finish", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => _conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "title_for_slack" => title_for_slack, | |
| "slack_channel_id" => channel_id, | |
| "slack_channel_url" => channel_url, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => _intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => _notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.invite_users_to_channel(channel_id, best_matches, slack_token) do | |
| {:ok, _} -> | |
| Logger.info("Invited users to channel") | |
| # Update Notion ticket with Slack channel link | |
| Notion.edit_slack_channel(notion_page_id, channel_url, notion_token) | |
| Logger.info("Notion ticket updated with Slack channel and Intercom conversation links") | |
| ticket = | |
| Tickets.get_ticket_by_intercom_conversation_id(conversation_id |> Integer.to_string()) | |
| Tickets.update_ticket(ticket, %{ | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "notion_ticket_name" => ticket_info["title"], | |
| "notion_children" => ticket_info["summary"], | |
| "slack_channel_name" => title_for_slack, | |
| "intercom_conversation_id" => Integer.to_string(conversation_id), | |
| "slack_channel_url" => channel_url | |
| }) | |
| Logger.info("Ticket updated in Database") | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| :ok | |
| {:error, | |
| %{ | |
| "error" => "already_in_channel", | |
| "errors" => [ | |
| %{"error" => "already_in_channel", "ok" => false, "user" => _} | |
| ], | |
| "ok" => false | |
| }} -> | |
| Logger.info("Users already in channel") | |
| ticket = | |
| Tickets.get_ticket_by_intercom_conversation_id(conversation_id |> Integer.to_string()) | |
| Tickets.update_ticket(ticket, %{ | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "notion_ticket_name" => ticket_info["title"], | |
| "notion_children" => ticket_info["summary"], | |
| "slack_channel_name" => title_for_slack, | |
| "intercom_conversation_id" => Integer.to_string(conversation_id), | |
| "slack_channel_url" => channel_url | |
| }) | |
| Logger.info("Ticket updated in Database") | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to invite users to channel") | |
| {:snooze, 5} | |
| end | |
| end | |
| ## THIRD ACTION | |
| # Starting function to create ticket and update existing channel | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_ticket_and_update_channel", | |
| "conversations" => conversations, | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case TicketGenerator.generate_ticket_info(conversations) do | |
| {:ok, ticket_info} -> | |
| # Get channel information | |
| slack_channel_id = channel["id"] | |
| slack_channel_url = channel["url"] | |
| Logger.info("Generated ticket info") | |
| schedule_next_task(%{ | |
| "task" => "create_ticket_and_update_channel_task_get_conversation_url", | |
| "ticket_info" => ticket_info, | |
| "conversation_id" => conversation_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to generate ticket info") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Separate task to get the conversation URL | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_ticket_and_update_channel_task_get_conversation_url", | |
| "ticket_info" => ticket_info, | |
| "conversation_id" => conversation_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| # Get the conversation URL as a separate step | |
| case Intercom.get_conversation_url(conversation_id, intercom_token) do | |
| {:ok, conversation_url} -> | |
| Logger.info("Retrieved Intercom conversation URL") | |
| schedule_next_task(%{ | |
| "task" => "create_ticket_and_update_channel_task_create_notion_ticket", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to get Intercom conversation URL") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Create the Notion ticket | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_ticket_and_update_channel_task_create_notion_ticket", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Notion.create_ticket( | |
| ticket_info["title"], | |
| ticket_info["summary"], | |
| conversation_url, | |
| notion_token, | |
| notion_database_id | |
| ) do | |
| {:ok, body} -> | |
| notion_url = body["url"] | |
| notion_page_id = body["id"] | |
| id_with_jmp = | |
| body["properties"]["ID"]["unique_id"]["prefix"] <> | |
| "-" <> | |
| Integer.to_string(body["properties"]["ID"]["unique_id"]["number"]) | |
| slug_for_title = Slugify.make_slug(ticket_info["title"]) | |
| title_for_slack = id_with_jmp <> "-" <> slug_for_title | |
| # Update the Notion ticket with the Slack channel link right away | |
| Notion.edit_slack_channel(notion_page_id, slack_channel_url, notion_token) | |
| schedule_next_task(%{ | |
| "task" => "create_ticket_and_update_channel_task_update_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Ticket created in Notion") | |
| :ok | |
| _ -> | |
| Logger.error("Failed to create ticket in Notion") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Update the Slack channel name and topic | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_ticket_and_update_channel_task_update_slack_channel", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| # Update the channel name | |
| case Slack.rename_slack_channel(slack_token, slack_channel_id, title_for_slack) do | |
| {:ok, _} -> | |
| # Update the channel topic | |
| case SlackChannel.set_topic(slack_channel_id, notion_url, slack_token) do | |
| {:ok, _} -> | |
| Logger.info("Channel updated in Slack") | |
| schedule_next_task(%{ | |
| "task" => "create_ticket_and_update_channel_task_fetch_intercom_admins", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to update channel topic") | |
| {:snooze, 5} | |
| end | |
| _ -> | |
| Logger.error("Failed to rename Slack channel") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Fetch Intercom admins | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_ticket_and_update_channel_task_fetch_intercom_admins", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_conversation_admins(conversation_id, intercom_token) do | |
| {:ok, intercom_admins} -> | |
| Logger.info("Fetched admins from Intercom") | |
| schedule_next_task(%{ | |
| "task" => "create_ticket_and_update_channel_task_fetch_slack_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch admins from Intercom") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Fetch Slack users and find best matches | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_ticket_and_update_channel_task_fetch_slack_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.get_users(slack_token) do | |
| {:ok, slack_users} -> | |
| {_status, best_matches} = | |
| UserMatcher.get_best_matches_for_adding_to_slack(intercom_admins, slack_users) | |
| schedule_next_task(%{ | |
| "task" => "create_ticket_and_update_channel_task_invite_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Matched Intercom admins with Slack users") | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch users from Slack") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Invite users to the channel and finalize the process | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "create_ticket_and_update_channel_task_invite_users", | |
| "ticket_info" => ticket_info, | |
| "conversation_url" => conversation_url, | |
| "conversation_id" => conversation_id, | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "slack_channel_id" => slack_channel_id, | |
| "slack_channel_url" => slack_channel_url, | |
| "title_for_slack" => title_for_slack, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => _intercom_token, | |
| "notion_token" => _notion_token, | |
| "notion_database_id" => _notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.invite_users_to_channel(slack_channel_id, best_matches, slack_token) do | |
| {:ok, _} -> | |
| Logger.info("Users invited to Slack channel") | |
| # Create ticket in database | |
| Tickets.create_ticket(%{ | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "notion_ticket_name" => ticket_info["title"], | |
| "notion_children" => ticket_info["summary"], | |
| "slack_channel_name" => title_for_slack, | |
| "intercom_conversation_url" => conversation_url, | |
| "intercom_conversation_id" => Integer.to_string(conversation_id), | |
| "slack_channel_url" => slack_channel_url, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Ticket created in Database") | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| :ok | |
| {:error, | |
| %{ | |
| "error" => "already_in_channel", | |
| "errors" => [ | |
| %{"error" => "already_in_channel", "ok" => false, "user" => _} | |
| ], | |
| "ok" => false | |
| }} -> | |
| Logger.info("Users already in channel") | |
| # Create ticket in database | |
| Tickets.create_ticket(%{ | |
| "notion_url" => notion_url, | |
| "notion_page_id" => notion_page_id, | |
| "notion_ticket_name" => ticket_info["title"], | |
| "notion_children" => ticket_info["summary"], | |
| "slack_channel_name" => title_for_slack, | |
| "intercom_conversation_url" => conversation_url, | |
| "intercom_conversation_id" => Integer.to_string(conversation_id), | |
| "slack_channel_url" => slack_channel_url, | |
| "user_id" => user_id | |
| }) | |
| Logger.info("Ticket created in Database") | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to invite users to channel") | |
| {:snooze, 5} | |
| end | |
| end | |
| ## FOURTH FUNCTION | |
| # First function in the update ticket and channel workflow | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel", | |
| "conversations" => _conversations, | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| # Start the workflow by getting the conversation URL | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_get_conversation_url", | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| end | |
| # Get conversation URL from Intercom | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel_task_get_conversation_url", | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_conversation_url(conversation_id, intercom_token) do | |
| {:ok, conversation_url} -> | |
| Logger.info("Retrieved Intercom conversation URL") | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_get_notion_page", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to retrieve Intercom conversation URL") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Get the Notion page details | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel_task_get_notion_page", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "ticket" => ticket, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Notion.get_page(ticket["id"], notion_token) do | |
| {:ok, body} -> | |
| notion_page_id = body["id"] | |
| Logger.info("Retrieved Notion page details") | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_fetch_intercom_admins", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to retrieve Notion page") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Fetch admins from Intercom | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel_task_fetch_intercom_admins", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.get_conversation_admins(conversation_id, intercom_token) do | |
| {:ok, intercom_admins} -> | |
| Logger.info("Fetched admins from Intercom") | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_fetch_slack_users", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch admins from Intercom") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Fetch users from Slack | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel_task_fetch_slack_users", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "intercom_admins" => intercom_admins, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.get_users(slack_token) do | |
| {:ok, slack_users} -> | |
| {_status, best_matches} = | |
| UserMatcher.get_best_matches_for_adding_to_slack(intercom_admins, slack_users) | |
| Logger.info("Fetched users from Slack and matched with Intercom admins") | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_invite_users", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to fetch users from Slack") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Invite users to Slack channel | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel_task_invite_users", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "best_matches" => best_matches, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.invite_users_to_channel(channel["id"], best_matches, slack_token) do | |
| {:ok, _} -> | |
| Logger.info("Users invited to Slack channel") | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_update_notion", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| {:error, | |
| %{ | |
| "error" => "already_in_channel", | |
| "errors" => [ | |
| %{"error" => "already_in_channel", "ok" => false, "user" => _} | |
| ], | |
| "ok" => false | |
| }} -> | |
| Logger.info("Users already in channel") | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_update_notion", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to invite users to channel") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Update Notion with the Intercom conversation link | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel_task_update_notion", | |
| "conversation_id" => conversation_id, | |
| "conversation_url" => conversation_url, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Notion.edit_intercom_conversation(notion_page_id, conversation_url, notion_token) do | |
| {:ok, _} -> | |
| Logger.info("Intercom conversation updated in Notion") | |
| schedule_next_task(%{ | |
| "task" => "update_ticket_and_channel_task_update_db", | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "conversation_url" => conversation_url, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => notion_database_id, | |
| "user_id" => user_id | |
| }) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to update Intercom conversation in Notion") | |
| {:snooze, 5} | |
| end | |
| end | |
| # Final step: Update the database record | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "update_ticket_and_channel_task_update_db", | |
| "conversation_id" => conversation_id, | |
| "channel" => channel, | |
| "notion_page_id" => notion_page_id, | |
| "conversation_url" => _conversation_url, | |
| "slack_token" => _slack_token, | |
| "intercom_token" => _intercom_token, | |
| "notion_token" => notion_token, | |
| "notion_database_id" => _notion_database_id, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| ticket = | |
| Tickets.get_ticket_by_intercom_conversation_id(conversation_id |> Integer.to_string()) | |
| case Notion.edit_slack_channel(notion_page_id, ticket.slack_channel_url, notion_token) do | |
| {:ok, _} -> | |
| Logger.info("Channel updated in Slack") | |
| if ticket do | |
| case Tickets.update_ticket(ticket, %{slack_channel_url: channel["url"]}) do | |
| {:ok, _updated_ticket} -> | |
| Logger.info("Ticket updated in DB") | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| :ok | |
| _ -> | |
| Logger.error("Failed to update ticket in DB") | |
| {:snooze, 5} | |
| end | |
| else | |
| Logger.error("Ticket not found in DB") | |
| {:snooze, 5} | |
| end | |
| _ -> | |
| Logger.error("Failed to update channel in Notion") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "handle_ticket_moved_to_done", | |
| "channel_id" => channel_id, | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Slack.send_message( | |
| channel_id, | |
| "Ticket has been completed and moved to Done", | |
| slack_token | |
| ) do | |
| {:ok, _} -> | |
| Logger.info("Message sent to Slack channel") | |
| schedule_next_task(%{ | |
| "task" => "handle_ticket_moved_to_done_task_send_intercom_message", | |
| "conversation_id" => conversation_id, | |
| "slack_token" => slack_token, | |
| "intercom_token" => intercom_token, | |
| "user_id" => user_id | |
| }) | |
| _ -> | |
| Logger.error("Failed to send message to Slack channel") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform( | |
| %Oban.Job{ | |
| args: %{ | |
| "task" => "handle_ticket_moved_to_done_task_send_intercom_message", | |
| "conversation_id" => conversation_id, | |
| "slack_token" => _slack_token, | |
| "intercom_token" => intercom_token, | |
| "user_id" => user_id | |
| } | |
| } = _job | |
| ) do | |
| case Intercom.send_message( | |
| conversation_id |> String.to_integer(), | |
| "Ticket has been completed and Closed , Thanks for your patience", | |
| intercom_token | |
| ) do | |
| {:ok, _} -> | |
| Logger.info("Message sent to Intercom conversation") | |
| ticket = | |
| Tickets.get_ticket_by_intercom_conversation_id(conversation_id) | |
| Tickets.update_ticket(ticket, %{is_done: true}) | |
| PubSub.broadcast( | |
| Integrator.PubSub, | |
| "tickets_update" <> Integer.to_string(user_id), | |
| {:tickets_updated, "Fetching all tickets"} | |
| ) | |
| Logger.info("Ticket updated in DB") | |
| :ok | |
| _ -> | |
| Logger.error("Failed to send message to Intercom conversation") | |
| {:snooze, 5} | |
| end | |
| end | |
| def perform(%Oban.Job{args: _} = _job) do | |
| :ok | |
| end | |
| def cancel(key) do | |
| from(j in Job, where: fragment("? ->> ? = ?", j.args, "id", ^key)) | |
| |> Oban.cancel_all_jobs() | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment