I am now running an interesting experiment: Use Discord for providing live chat product support from GitHub repositories. In this post, you'll learn how to create a customer support portal using PHP to control access to a Discord channel.
The problem, in a nutshell, is that I get various requests on the issue trackers for my 80+ GitHub repos that aren't actual issues with the product but folks who just need some assistance. Opening an issue on an issue tracker should be one of:
- An actual bug in the product itself.
- A "bug" in the documentation (e.g. missing documentation).
- A feature request.
Asking for help with understanding something is not really compatible with an issue tracker although it might be a disguised documentation issue. The main reason is that there is no hard-and-fast "end of issue" with support requests. Such issues can remain open for years as a result of waiting for the person to respond in the affirmative that they understand how to use a product.
My previous solution was to use forum software. While that works, it can be days before anyone notices the request for assistance and receive a response. Most folks would prefer a solution where there can be back-and-forth discussion in real-time.
Most live chat technical support solutions out there are expensive and primarily text-based. Enter Discord: A free chat system for text, audio, and video. However, Discord, by itself, is not really prepared to handle the workflow of:
- User enters channel and announces themselves and their problem.
- User gets picked up by a support person for direct messaging.
- Gently kick the user out of the system when the support request is complete.
- Repeat steps 1-3 for the next user.
From my own experience with running multiple forums, it is important to do two things when something is publicly accessible to streamline support:
- Precisely control access to the Discord channel to prevent bots and the like from spamming the support mechanism.
- Gather important meta-information about the incoming user (source GitHub repo, license info, etc).
After creating a Discord account and a new "server" for the technical support channel, go through the settings and adjust what you want to allow anyone to be able to do (file uploads, view the chat history, time delays between messages, etc). Once satisfied, it is time to get coding the missing bits that control server/channel access.
We'll use the Discord SDK for PHP to create a basic portal webpage that sends information to a Discord channel, creates a temporary, one-time use invite, and finally redirects the user into Discord. This will form the basis of the live support system and can be expanded later to, for example, require a CAPTCHA to be solved or accept a payment via Stripe to manage access. No one can get in without a valid invite code and invites are only issued when all checks within the script pass.
<?php
require_once "support/sdk_discord.php";
require_once "support/http.php";
function DisplayError($title, $msg)
{
// Output website header here.
?>
<div class="contentwrap">
<div class="contentwrapinner">
<h1><?=htmlspecialchars($title)?></h1>
<p><?=$msg?></p>
</div>
</div>
<?php
// Output website footer here.
exit();
}
$githubuser = "[YOUR_GITHUB_USER]";
$webhookurl = "[CHANNEL_WEBHOOK_URL]";
$bottoken = "[YOUR_BOT_TOKEN]";
$channelid = "[INVITE_CHANNEL_ID]";
if (!isset($_SERVER["HTTP_REFERER"])) DisplayError("Missing Referrer", "This page was accessed directly. Please enter via a <a href=\"https://github.com/" . $githubuser . "/\">valid repository on GitHub</a>.");
// Check the HTTP referer header to verify the user is coming from a valid repository.
$url = HTTP::ExtractURL($_SERVER["HTTP_REFERER"]);
if ($url["host"] !== "github.com" || strncmp($url["path"], "/" . $githubuser . "/", strlen("/" . $githubuser . "/")) != 0) DisplayError("Invalid Referrer", "This page was accessed incorrectly. Please enter via the relevant <a href=\"https://github.com/" . $githubuser . "/\">repository on GitHub</a>.");
// Send initial message to the main channel.
$options = array(
"content" => str_replace("https://", "", HTTP::CondenseURL($url))
);
$result = DiscordSDK::SendWebhookMessage($webhookurl, $options);
if (!$result["success"]) DisplayError("Discord Error", "An error occurred while attempting to access Discord. " . htmlspecialchars($result["error"] . " (" . $result["errorcode"] . ")"));
// Create a temporary invite.
$discord = new DiscordSDK();
$discord->SetAccessInfo("Bot", $bottoken);
$options = array(
"max_age" => 1800,
"max_uses" => 1,
"unique" => true,
"temporary" => true
);
$result = $discord->RunAPI("POST", "channels/" . $channelid . "/invites", $options);
if (!$result["success"]) DisplayError("Discord Error", "An error occurred while attempting to setup Discord. " . htmlspecialchars($result["error"] . " (" . $result["errorcode"] . ")"));
// Redirect the user's browser to the invite.
$url = "https://discord.gg/" . $result["data"]["code"];
header("Location: " . $url);
?>
The above PHP script sits on a public web server you have access to. Modify the various string placeholders with valid tokens and information. There are step-by-step instructions on how to set up Discord webhooks and bots on the Discord SDK for PHP repository.
Once the above script is configured, then it is time to connect it to a repository and begin accepting visitors in the Discord support channel. In the README markdown for the repo, add a dynamic button:
[![Discord](https://img.shields.io/discord/INVITE_CHANNEL_ID?label=chat&logo=discord)](URL_OF_SCRIPT)
Substitute in the correct values for INVITE_CHANNEL_ID
and URL_OF_SCRIPT
. Commit the changes to the repository.
If all goes well, a shield/button with the Discord logo, the word "chat" and the number of online users will appear on the respository. Using a Private Web Browsing/Incognito window can be used to verify that clicking the new button lets a user into Discord.
Only those who come from the source repository will have access to the Discord channel. Everyone else will be rejected (e.g. someone visiting via a fork of the source repo).
Enjoy your new live chat product support!
Top comments (0)