Skip to content

Commit

Permalink
Merge branch 'brainboxdotcc:dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Henonicks authored Sep 16, 2023
2 parents 1f4c9c7 + f490fd3 commit 71305e2
Show file tree
Hide file tree
Showing 107 changed files with 2,954 additions and 2,555 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
2 changes: 1 addition & 1 deletion docpages/06_advanced_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

* \subpage clusters-shards-guilds "Clusters, Shards and Guilds"
* \subpage thread-model "Thread Model"
* \subpage coding-standards "Coding Style Standards"
* \subpage coding-standards
* \subpage unit-tests "Unit Tests"
* \subpage lambdas-and-locals "Ownership of local variables and safely transferring into a lambda"
* \subpage governance "Project Governance"
Expand Down
120 changes: 78 additions & 42 deletions docpages/advanced_reference/coding_style_standards.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
\page coding-standards Coding Style Standards

This page lists the coding style we stick to when maintaining the D++ library. If you are submitting a pull request or other code contribution to the library, you should stick to the styles listed below. If something is not covered here, ask on the [official discord server](https://discord.gg/dpp)!
This page lists the coding style we stick to when maintaining the D++ library. If you are submitting a pull request or other code contribution to the library, you should stick to the styles listed below. If something is not covered here, ask on the [official Discord server](https://discord.gg/dpp)!

## Class Names, Function Names, and Method Names

## Class names, function names and method names
All class, variable/member, function and method names should use `snake_case`, similar to the style of the C++ standard library.

## Enums
Enums and their values should be `snake_case` as with class, function and method names. You do not need to use `enum class`, so make sure that enum values are prefixed with a prefix to make them unique and grouped within the IDE, e.g. `ll_debug`, `ll_trace` etc.

Enums and their values should be `snake_case` as with class, function and method names. You do not need to use `enum class`, so make sure that enum values are prefixed with a prefix to make them unique and grouped within the IDE, e.g. `ll_debug`, `ll_trace`, etc.

## Curly Braces, Brackets, etc.

## Curly Braces, Brackets etc
This covers your standard Curly Braces (commonly known as squiggly brackets), and Lists.
This covers your standard Curly Braces (commonly known as squiggly brackets), and lists.

### Curly Braces

Curly Braces should be on the same line as the keyword, for example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
void foo() {
if (a == b) {
c();
}
while(true) {
// ...
}
if (a == b) {
c();
} else {
d();
}

while (true) {
// ...
}

switch (a) {
case 1:
c();
break;
case 2:
d();
break;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand All @@ -33,28 +47,42 @@ This applies to functions, `while` statements, `if` statements, lambdas, nearly

Lists should have a space after the comma in parameter lists, and after opening brackets and before closing brackets except when calling a function, for example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
std::vector<std::string> clowns = { "pennywise", "bobo" };

evaluate_clown(clowns[0], evilness(2.5, factor));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Dot (.) Notation
When using the dot notation repeatedly (For example, creating an embed.), you should start each `.function()` on a new line, as such:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
stuff{}
.add_stuff()
.add_stuff();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

## Indentation

Indentation should always be tab characters. It is up to you how wide you set tab characters in your editor for your personal tastes. All code blocks delimited within curly braces should be indented neatly and uniformly.

## Constants and \#define macros
## Constants and \#define Macros

Constants and macros should be all `UPPERCASE` with `SNAKE_CASE` to separate words. Macros should not have any unexpected side effects.

## Comments

All comments should be in `doxygen` format (similar to javadoc). Please see existing class definitions for an example. You should use doxygen style comments in a class definition inside a header file, and can use any other comment types within the .cpp file. Be liberal with comments, especially if your code makes any assumptions!

## Spell checks
## Spell Checks

To prevent typos, a GitHub-Action checks the documentation. If it fails for a word that was falsely flagged, you can add them to `.cspell.json`.

## Symbol exporting
## Symbol Exporting

If you export a class which is to be accessible to users, be sure to prefix it with the `DPP_EXPORT` macro, for example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
class DPP_EXPORT my_new_class {
public:
int hats;
Expand All @@ -64,38 +92,47 @@ public:
The `DPP_EXPORT` macro ensures that on certain platforms (notably Windows) the symbol is exported to be available to the library user.
## Public vs private vs protected
## Public vs Private vs Protected
It is a design philosophy of D++ that everything possible in a class should be public, unless the user really does not need it (you should consider justifying in comments why) or user adjustment of the variable could badly break the functioning of the library. Avoid the use of accessors for setting/getting values in a class, except for bit fields, where you should provide accessors for setting and getting individual bits (for example, see `user.h`), or in the event you want to provide a "fluent" interface. The exception to this is where you want to provide a logic validation of a field, for example if you have a string field with a minimum and maximum length, you can provide a setter the user can *optionally use* which will validate their input.
## Exceptions
All exceptions thrown should derive from dpp::exception (see dpp/exception.h) - when validating string lengths, a string which is too long should be truncated using dpp::utility::utf8substr and any strings that are too short should throw a dpp::length_exception.
All exceptions thrown should derive from dpp::exception (see `dpp/exception.h`) - when validating string lengths, a string which is too long should be truncated using dpp::utility::utf8substr and any strings that are too short should throw a dpp::length_exception.
## Inheritance
Keep levels of inheritance low. If you need to inherit more than 3 levels deep, it is probable that the design could be simplified. Remember that at scale, there can be tens of millions of certain classes and each level of virtual nesting adds to the `vtable` of that object's instance in RAM.
## Bit field packing
Where discord provides boolean flags, if the user is expected to store many of the object in RAM, or in cache, you should pack all these booleans into bit fields (see `user.h` and `channel.h` for examples). In the event that the object is transient, such as an interaction or a message, packing the data into bit fields is counter intuitive. Remember that you should provide specific accessors for bit field values!
## Bit Field Packing
Where Discord provides boolean flags, if the user is expected to store many of the objects in RAM, or in cache, you should pack all these booleans into bit fields (see `user.h` and `channel.h` for examples). In the event that the object is transient, such as an interaction or a message, packing the data into bit fields is counter intuitive. Remember that you should provide specific accessors for bit field values!
## Keep Dependencies Internal!
## Keep dependencies internal!
Where you are making use of an external dependency such as `opus` or `libssl`, do not place references to the types/structs, or the header files of these external libraries within the header files of D++. Doing so adds that library as a public dependency to the project (which is bad!). Instead make an opaque class, and/or forward-declare the structs (for examples see `sslclient.h` and `discordvoiceclient.h`).
## API type names
Where discord provide a name in PascalCase we should stick as closely to that name as possible but convert it to `snake_case`. For example, GuildMember would become `guild_member`.
## API Type Names
Where Discord provides a name in PascalCase we should stick as closely to that name as possible but convert it to `snake_case`. For example, GuildMember would become `guild_member`.
## Don't introduce any platform-specific code
Do not introduce platform specific (e.g. windows only) code or libc functions. If you really must use these functions safely wrap them e.g. in `#ifdef _WIN32` and provide a cross-platform alternative so that it works for everyone.
## Don't Introduce Any Platform-Specific Code
## C++ version
Do not introduce platform specific (e.g. Windows only) code or libc functions. If you really must use these functions safely wrap them e.g. in `#ifdef _WIN32` and provide a cross-platform alternative so that it works for everyone.
The code must work with the C++17 standard.
## C++ Version
## Select the right size type for numeric types
If a value will only hold values up to 255, use `uint8_t`. If a value cannot hold over 65536, use `uint16_t`. These types can help use a lot less ram at scale.
The code must work with the C++17 standard, unless, for an optional feature that can be enabled and that uses a more recent standard (e.g. Coroutines).
## Fluent design
Where possible, if you are adding methods to a class you should consider fluent design. Fluent design is the use of class methods tha return a reference to self (via `return *this`), so that you can chain object method calls together (in the way `dpp::message` and `dpp::embed` do). For example:
## Select the Right Size Type for Numeric Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
If a value will only hold values up to 255, use `uint8_t`. If a value cannot hold over 65536, use `uint16_t`. These types can help use a lot less RAM at scale.
## Fluent Design
Where possible, if you are adding methods to a class you should consider fluent design. Fluent design is the use of class methods that return a reference to self (via `return *this`), so that you can chain object method calls together (in the way dpp::message and dpp::embed do). For example:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
class DPP_EXPORT my_new_class {
public:
int hats;
Expand All @@ -114,27 +151,26 @@ my_new_class& my_new_class::set_clowns(int new_clowns) {
clowns = new_clowns;
return *this;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This would allow the user to do this:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
dpp::my_new_class nc;
nc.set_hats(3).set_clowns(9001);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

## Keep all D++ related types in the dpp namespace
## Keep All D++ Related Types in the dpp Namespace

All types for the library should be within the `dpp` namespace. There are a couple of additional namespaces, e.g. `dpp::utility` for static standalone helper functions and helper classes, and `dpp::events` for internal websocket event handlers.
All types for the library should be within the `dpp` namespace. There are a couple of additional namespaces, e.g. dpp::utility for static standalone helper functions and helper classes, and dpp::events for internal websocket event handlers.

## Commit messages and Git
## Commit Messages and Git

All pull requests ("PRs") should be submitted against the `dev` branch in GitHub.

### Naming conventions
### Naming Conventions

It’s good to have descriptive commit messages, or PR titles so that other contributors can understand about your commit or the PR Created. Commits must be prefixed with a type, which consists of a noun, `feat`, `fix`, etc., followed by a colon and a space. Other commit types can be `breaking`, `docs`, `refactor`, `deprecate`, `perf`, `test`, `chore` and `misc`. Read [conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.3/) for more information on how we like to format commit messages.
It’s good to have descriptive commit messages, or PR titles so that other contributors can understand about your commit or the PR Created. Commits must be prefixed with a type, which consists of a noun, `feat`, `fix`, etc., followed by a colon and a space. Other commit types can be `breaking`, `docs`, `refactor`, `deprecate`, `perf`, `test`, `chore`, and `misc`. Read [conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.3/) for more information on how we like to format commit messages.

### GitHub Actions

Expand Down Expand Up @@ -175,4 +211,4 @@ By making a contribution to this project, I certify that:
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
```
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;
}
Loading

0 comments on commit 71305e2

Please sign in to comment.