Skip to content

Commit

Permalink
docs: add auto testing of examples (#854)
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis authored Sep 14, 2023
1 parent faf4cbc commit fd3f875
Show file tree
Hide file tree
Showing 87 changed files with 2,627 additions and 2,591 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/test-docs-examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Test compile documentation examples
on:
push:
branches:
- 'dev'
files:
- '**Doxyfile'
- '**docpages/example_code/**'
pull_request:
files:
- '**Doxyfile'
- '**docpages/example_code/**'
workflow_dispatch:

jobs:
test_docs_examples:
name: Test build examples
runs-on: ubuntu-22.04

steps:
- name: Harden Runner
uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
with:
egress-policy: audit

- name: Checkout D++
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
with:
submodules: recursive

- name: Install apt packages
run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt-get update && sudo apt-get install -y g++-12 libsodium-dev libopus-dev zlib1g-dev libmpg123-dev liboggz-dev cmake libfmt-dev

- name: Generate CMake
run: mkdir build && cd build && cmake -DDPP_NO_VCPKG=ON -DAVX_TYPE=T_fallback -DDPP_CORO=ON -DCMAKE_BUILD_TYPE=Debug ..
env:
CXX: g++-12

- name: Build Project
run: cd build && make -j2 && sudo make install

- name: Test compile examples
run: cd docpages/example_code && mkdir build && cd build && cmake .. && make -j2
env:
CXX: g++-12
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ build
buildtools/composer.phar
src/build
cmake-build-debug
docpages/example_code/build

# tests
test
Expand All @@ -28,4 +29,4 @@ core
config.json
.misspell-fixer.ignore
compile_commands.json
src/dpp/dpp.rc
src/dpp/dpp.rc
6 changes: 4 additions & 2 deletions Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,8 @@ EXCLUDE = deps \
build \
include/dpp/format \
include/dpp/nlohmann \
docpages/include
docpages/include \
docpages/example_code

# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
Expand Down Expand Up @@ -830,7 +831,8 @@ EXCLUDE_SYMBOLS = nlohmann::* \
# that contain example code fragments that are included (see the \include
# command).

EXAMPLE_PATH =docpages/include
EXAMPLE_PATH = docpages/include \
docpages/example_code

# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
Expand Down
45 changes: 45 additions & 0 deletions docpages/example_code/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#
# D++ (DPP), The Lightweight C++ Discord Library
#
# Copyright 2021 Craig Edwards <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# Example programs test compilation
# This build script is executed by a GitHub action to ensure all example
# programs compile correctly. It does not attempt to run them, as there
# is no way to know if the program successfully did its thing, plus
# examples do not have a valid token. This build script assumes the
# following system dependencies are available:
#
# g++-12 or later
# liboggz-dev
# libmpg123-dev
# dpp latest master with -DDPP_CORO=ON installed sytemwide

cmake_minimum_required (VERSION 3.16)
project(documentation_tests)

string(ASCII 27 Esc)

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDPP_CORO -std=c++20 -pthread -O0 -fPIC -rdynamic -DFMT_HEADER_ONLY -Wall -Wextra -Wpedantic -Werror -Wno-unused-parameter")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")

file(GLOB example_list ./*.cpp)
foreach (example ${example_list})
get_filename_component(examplename ${example} NAME)
message(STATUS "Found example '${Esc}[1;34m${examplename}${Esc}[m'")
add_executable(${examplename}_out ${example})
target_link_libraries(${examplename}_out dl dpp mpg123 oggz)
endforeach(example)
34 changes: 34 additions & 0 deletions docpages/example_code/attachments1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <dpp/dpp.h>

int main() {
dpp::cluster bot("token");

bot.on_log(dpp::utility::cout_logger());

/* The event is fired when someone issues your commands */
bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) {
/* Check which command they ran */
if (event.command.get_command_name() == "file") {

dpp::message msg(event.command.channel_id, "Hey there, I've got a new file!");

/* attach the file to the message */
msg.add_file("foobar.txt", dpp::utility::read_file("path_to_your_file.txt"));

/* Reply to the user with the message, with our file attached. */
event.reply(msg);
}
});

bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {

/* Create and register a command when the bot is ready */
bot.global_command_create(dpp::slashcommand("file", "Send a message with a file attached!", bot.me.id));
}
});

bot.start(dpp::st_wait);

return 0;
}
41 changes: 41 additions & 0 deletions docpages/example_code/attachments2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <dpp/dpp.h>

int main() {
dpp::cluster bot("token");

bot.on_log(dpp::utility::cout_logger());

/* The event is fired when someone issues your commands */
bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) {
/* Check which command they ran */
if (event.command.get_command_name() == "file") {

/* Request the image from the URL specified and capture the event in a lambda. */
bot.request("https://dpp.dev/DPP-Logo.png", dpp::m_get, [event](const dpp::http_request_completion_t & httpRequestCompletion) {

/* Create a message */
dpp::message msg(event.command.channel_id, "This is my new attachment:");

/* Attach the image to the message, only on success (Code 200). */
if (httpRequestCompletion.status == 200) {
msg.add_file("logo.png", httpRequestCompletion.body);
}

/* Send the message, with our attachment. */
event.reply(msg);
});
}
});

bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {

/* Create and register a command when the bot is ready */
bot.global_command_create(dpp::slashcommand("file", "Send a message with an image attached from the internet!", bot.me.id));
}
});

bot.start(dpp::st_wait);

return 0;
}
41 changes: 41 additions & 0 deletions docpages/example_code/attachments3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <dpp/dpp.h>

int main() {
dpp::cluster bot("token");

bot.on_log(dpp::utility::cout_logger());

/* The event is fired when someone issues your commands */
bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) {
/* Check which command they ran */
if (event.command.get_command_name() == "file") {

/* Create a message. */
dpp::message msg(event.command.channel_id, "");

/* Attach the image to the message we just created. */
msg.add_file("image.jpg", dpp::utility::read_file("path_to_your_image.jpg"));

/* Create an embed. */
dpp::embed embed;
embed.set_image("attachment://image.jpg"); /* Set the image of the embed to the attached image. */

/* Add the embed to the message. */
msg.add_embed(embed);

event.reply(msg);
}
});

bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {

/* Create and register a command when the bot is ready */
bot.global_command_create(dpp::slashcommand("file", "Send a local image along with an embed with the image!", bot.me.id));
}
});

bot.start(dpp::st_wait);

return 0;
}
67 changes: 67 additions & 0 deletions docpages/example_code/autocomplete.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <dpp/dpp.h>

int main()
{
dpp::cluster bot("token");

bot.on_log(dpp::utility::cout_logger());

bot.on_ready([&bot](const dpp::ready_t & event) {
if (dpp::run_once<struct register_bot_commands>()) {

/* Create a new global command once on ready event */
bot.global_command_create(dpp::slashcommand("blep", "Send a random adorable animal photo", bot.me.id)
.add_option(
/* If you set the auto complete setting on a command option, it will trigger the on_autocomplete
* event whenever discord needs to fill information for the choices. You cannot set any choices
* here if you set the auto complete value to true.
*/
dpp::command_option(dpp::co_string, "animal", "The type of animal").set_auto_complete(true)
)
);
}
});

/* The interaction create event is fired when someone issues your commands */
bot.on_slashcommand([&bot](const dpp::slashcommand_t & event) {

/* Check which command they ran */
if (event.command.get_command_name() == "blep") {
/* Fetch a parameter value from the command parameters */
std::string animal = std::get<std::string>(event.get_parameter("animal"));
/* Reply to the command. There is an overloaded version of this
* call that accepts a dpp::message so you can send embeds.
*/
event.reply("Blep! You chose " + animal);
}
});

/* The on_autocomplete event is fired whenever discord needs information to fill in a command options's choices.
* You must reply with a REST event within 500ms, so make it snappy!
*/
bot.on_autocomplete([&bot](const dpp::autocomplete_t & event) {
for (auto & opt : event.options) {
/* The option which has focused set to true is the one the user is typing in */
if (opt.focused) {
/* In a real world usage of this function you should return values that loosely match
* opt.value, which contains what the user has typed so far. The opt.value is a variant
* and will contain the type identical to that of the slash command parameter.
* Here we can safely know it is string.
*/
std::string uservalue = std::get<std::string>(opt.value);
bot.interaction_response_create(event.command.id, event.command.token, dpp::interaction_response(dpp::ir_autocomplete_reply)
.add_autocomplete_choice(dpp::command_option_choice("squids", "lots of squids"))
.add_autocomplete_choice(dpp::command_option_choice("cats", "a few cats"))
.add_autocomplete_choice(dpp::command_option_choice("dogs", "bucket of dogs"))
.add_autocomplete_choice(dpp::command_option_choice("elephants", "bottle of elephants"))
);
bot.log(dpp::ll_debug, "Autocomplete " + opt.name + " with value '" + uservalue + "' in field " + event.name);
break;
}
}
});

bot.start(dpp::st_wait);

return 0;
}
60 changes: 60 additions & 0 deletions docpages/example_code/cache_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <dpp/dpp.h>
#include <sstream>

int main() {
/* Create bot */
dpp::cluster bot("token", dpp::i_default_intents | dpp::i_message_content); /* Because we're handling messages, we need to use the "i_message_content" intent! */

/* Create a cache to contain types of dpp::message */
dpp::cache<dpp::message> message_cache;

bot.on_log(dpp::utility::cout_logger());

/* Message handler */
bot.on_message_create([&](const dpp::message_create_t &event) {
/* Make a permanent pointer using new, for each message to be cached */
dpp::message* m = new dpp::message();

/* Store the message into the pointer by copying it */
*m = event.msg;

/* Store the new pointer to the cache using the store() method */
message_cache.store(m);
});

/* The event is fired when someone issues your commands */
bot.on_slashcommand([&bot, &message_cache](const dpp::slashcommand_t& event) {
/* Check which command they ran */
if (event.command.get_command_name() == "get") {

dpp::message* find_msg = message_cache.find(std::get<std::string>(event.get_parameter("message_id")));

/* If find_msg is null, tell the user and return. */
if (!find_msg) {
event.reply("There is no message cached with this ID");
return;
}

event.reply("This message had the following content: " + find_msg->content);
}
});

bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {

/* Create a new command. */
dpp::slashcommand newcommand("get", "Get the contents of a message that was cached via an id", bot.me.id);

/* Add a parameter option. */
newcommand.add_option(dpp::command_option(dpp::co_string, "message_id", "The ID of the message you want to find", true));

/* Register the command */
bot.global_command_create(newcommand);
}
});

/* Start bot */
bot.start(dpp::st_wait);

return 0;
}
Loading

0 comments on commit fd3f875

Please sign in to comment.