stage changes
This commit is contained in:
commit
ab3a1cb6b1
5
.clang-format
Normal file
5
.clang-format
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
---
|
||||
Language: Cpp
|
6
.containerignore
Normal file
6
.containerignore
Normal file
@ -0,0 +1,6 @@
|
||||
**
|
||||
!lib/**
|
||||
!CMakeLists.txt
|
||||
!main.cc
|
||||
!include.hh
|
||||
!extern.cc
|
118
.gitignore
vendored
Normal file
118
.gitignore
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
build*/
|
||||
.floo
|
||||
token.dat
|
||||
cmake-build-*/
|
||||
scratch.txt
|
||||
env
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Created by https://www.gitignore.io/api/jetbrains+all
|
||||
|
||||
### JetBrains+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff:
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.xml
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# CMake
|
||||
cmake-build-debug/
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
### JetBrains+all Patch ###
|
||||
# Ignores the whole idea folder
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
.idea/
|
||||
|
||||
# End of https://www.gitignore.io/api/jetbrains+all
|
||||
|
||||
# Created by https://www.gitignore.io/api/visualstudiocode
|
||||
# Edit at https://www.gitignore.io/?templates=visualstudiocode
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
|
||||
# End of https://www.gitignore.io/api/visualstudiocode
|
||||
|
||||
*.log
|
59
CMakeLists.txt
Normal file
59
CMakeLists.txt
Normal file
@ -0,0 +1,59 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(discord-oscuro LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic")
|
||||
|
||||
include(cmake/macros.cmake)
|
||||
include(cmake/CPM.cmake)
|
||||
|
||||
CPMAddPackage("gh:DiscordPP/discordpp#daf04ea")
|
||||
CPMAddPackage("gh:DiscordPP/rest-simpleweb#4cf911b")
|
||||
CPMAddPackage("gh:DiscordPP/websocket-simpleweb#9082991")
|
||||
CPMAddPackage("gh:DiscordPP/plugin-native#238b7e8")
|
||||
CPMAddPackage("gh:DiscordPP/plugin-overload#8862ac5")
|
||||
CPMAddPackage("gh:DiscordPP/plugin-responder#3c2c485")
|
||||
CPMAddPackage("gh:DiscordPP/plugin-interactionhandler#df07fd3")
|
||||
CPMAddPackage("gh:DiscordPP/plugin-ratelimit#2c8cb34")
|
||||
CPMAddPackage("gh:libcpr/cpr#1.10.4")
|
||||
|
||||
set(DISCORDPP_USE_BOOST OFF CACHE BOOL "Override option" FORCE)
|
||||
|
||||
CREATE_DISCORDPP_DEFINITIONS()
|
||||
CREATE_DISCORDPP_INCLUDE()
|
||||
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
|
||||
if(${DISCORDPP_USE_BOOST})
|
||||
find_package(Boost 1.71.0 REQUIRED system date_time)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
source/main.cpp
|
||||
)
|
||||
|
||||
#target_precompile_headers(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/source/main.hpp)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${Boost_LIBRARIES}
|
||||
Threads::Threads
|
||||
${OPENSSL_LIBRARIES}
|
||||
discordpp
|
||||
discordpp-rest-simpleweb
|
||||
discordpp-websocket-simpleweb
|
||||
discordpp-plugin-native
|
||||
discordpp-plugin-overload
|
||||
discordpp-plugin-responder
|
||||
discordpp-plugin-interactionhandler
|
||||
discordpp-plugin-ratelimit
|
||||
cpr::cpr
|
||||
)
|
||||
|
||||
copy_file("env")
|
||||
|
29
Containerfile
Normal file
29
Containerfile
Normal file
@ -0,0 +1,29 @@
|
||||
FROM alpine:latest AS build
|
||||
|
||||
RUN apk update
|
||||
RUN apk add --no-cache \
|
||||
build-base \
|
||||
cmake \
|
||||
samurai \
|
||||
boost-dev \
|
||||
git \
|
||||
openssl-dev
|
||||
|
||||
WORKDIR /echo_bot
|
||||
COPY . .
|
||||
RUN cmake -B build -G Ninja .
|
||||
RUN cmake --build build
|
||||
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk update
|
||||
RUN apk add --no-cache \
|
||||
libgcc \
|
||||
libstdc++ \
|
||||
libc6-compat \
|
||||
openssl-dev
|
||||
|
||||
WORKDIR /echo_bot
|
||||
COPY --from=build /echo_bot/build/echo_bot .
|
||||
CMD source /run/secrets/discord-oscuro-env; ./echo_bot
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 George Kusayko <L-Nafaryus>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
11
README.md
Normal file
11
README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Oscuro - Discord Bot (c++)
|
||||
|
||||
## Note
|
||||
- Create `env` file:
|
||||
```sh
|
||||
export BOT_TOKEN="Bot ....."
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
**oscuro** is licensed under the [MIT License](LICENSE).
|
23
cmake/CPM.cmake
Normal file
23
cmake/CPM.cmake
Normal file
@ -0,0 +1,23 @@
|
||||
set(CPM_DOWNLOAD_VERSION 0.38.1)
|
||||
|
||||
if(CPM_SOURCE_CACHE)
|
||||
# Expand relative path. This is important if the provided path contains a tilde (~)
|
||||
get_filename_component(CPM_SOURCE_CACHE ${CPM_SOURCE_CACHE} ABSOLUTE)
|
||||
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
|
||||
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
|
||||
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
|
||||
else()
|
||||
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
endif()
|
||||
|
||||
if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
|
||||
message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}")
|
||||
file(DOWNLOAD
|
||||
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
|
||||
${CPM_DOWNLOAD_LOCATION}
|
||||
)
|
||||
endif()
|
||||
|
||||
include(${CPM_DOWNLOAD_LOCATION})
|
8
cmake/macros.cmake
Normal file
8
cmake/macros.cmake
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
function(copy_file FILE)
|
||||
if (EXISTS ${CMAKE_SOURCE_DIR}/${FILE})
|
||||
configure_file(${FILE} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
|
||||
elseif (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${FILE})
|
||||
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${FILE})
|
||||
endif ()
|
||||
endfunction()
|
22
source/bot.hpp
Normal file
22
source/bot.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <discordpp/bot.hh>
|
||||
#include <discordpp/rest-simpleweb.hh>
|
||||
#include <discordpp/websocket-simpleweb.hh>
|
||||
#include <discordpp/plugin-native.hh>
|
||||
#include <discordpp/plugin-overload.hh>
|
||||
#include <discordpp/plugin-responder.hh>
|
||||
#include <discordpp/plugin-interactionhandler.hh>
|
||||
#include <discordpp/plugin-ratelimit.hh>
|
||||
|
||||
|
||||
using Bot = discordpp::PluginRateLimit
|
||||
<discordpp::PluginInteractionHandler
|
||||
<discordpp::PluginResponder
|
||||
<discordpp::PluginOverload
|
||||
<discordpp::PluginNative
|
||||
<discordpp::WebsocketSimpleWeb
|
||||
<discordpp::RestSimpleWeb
|
||||
<discordpp::Bot>>>>>>>;
|
||||
|
||||
namespace dpp = discordpp;
|
19
source/commands.hpp
Normal file
19
source/commands.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "bot.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
using event = std::function<void(const json)>;
|
||||
|
||||
|
||||
auto help(const std::shared_ptr<Bot>& bot)
|
||||
{
|
||||
return [&bot](const dpp::MessageCreateEvent& msg)
|
||||
{
|
||||
|
||||
};
|
||||
}
|
218
source/main.cpp
Normal file
218
source/main.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
|
||||
#ifdef ASIO_STANDALONE
|
||||
#include <asio.hpp>
|
||||
#else
|
||||
#include <boost/asio.hpp>
|
||||
namespace asio = boost::asio;
|
||||
#endif
|
||||
|
||||
#include "bot.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
#include "utils.hpp"
|
||||
#include "commands.hpp"
|
||||
|
||||
|
||||
int main() {
|
||||
dpp::log::filter = dpp::log::debug;
|
||||
dpp::log::out = &std::cerr;
|
||||
|
||||
std::cout << "Starting bot ..." << std::endl;
|
||||
|
||||
std::string token = getToken();
|
||||
if (token.empty()) {
|
||||
std::cerr << "Failed to read token from environment. Exiting ..." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dpp::User self;
|
||||
auto bot = std::make_shared<Bot>();
|
||||
|
||||
bot->debugUnhandled = true;
|
||||
bot->intents = dpp::intents::NONE | dpp::intents::GUILD_MESSAGES;
|
||||
|
||||
bot->handlers.insert({
|
||||
"READY",
|
||||
[&self](dpp::ReadyEvent ready){ self = *ready.user; }
|
||||
});
|
||||
|
||||
bot->prefix = "/";
|
||||
|
||||
bot->respond("test", help(bot));
|
||||
bot->respond("help", "Mention me and I'll echo your message back!");
|
||||
|
||||
bot->respond("about", [&bot](dpp::MessageCreateEvent msg) {
|
||||
std::ostringstream content;
|
||||
content << "Sure thing, "
|
||||
<< *(msg.member->nick ? msg.author->username : msg.member->nick)
|
||||
<< "!\n"
|
||||
<< "I'm a simple bot meant to demonstrate the "
|
||||
"Discord++ library.\n"
|
||||
<< "You can learn more about Discord++ at "
|
||||
"https://discord.gg/VHAyrvspCx";
|
||||
bot->createMessage()
|
||||
->channel_id(*msg.channel_id)
|
||||
->content(content.str())
|
||||
->run();
|
||||
});
|
||||
|
||||
bot->respond("lookatthis", [&bot](dpp::MessageCreateEvent msg) {
|
||||
std::ifstream ifs("image.jpg", std::ios::binary);
|
||||
if (!ifs) {
|
||||
std::cerr << "Couldn't load file 'image.jpg'!\n";
|
||||
return;
|
||||
}
|
||||
ifs.seekg(0, std::ios::end);
|
||||
std::ifstream::pos_type fileSize = ifs.tellg();
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
auto file = std::make_shared<std::string>(fileSize, '\0');
|
||||
ifs.read(file->data(), fileSize);
|
||||
|
||||
bot->createMessage()
|
||||
->channel_id(*msg.channel_id)
|
||||
->content("Look at this photograph")
|
||||
->filename("image.jpg")
|
||||
->filetype("image/jpg")
|
||||
->file(file)
|
||||
->run();
|
||||
});
|
||||
|
||||
bot->respond("notacat", [&bot](dpp::MessageCreateEvent msg)
|
||||
{
|
||||
cpr::Response res = cpr::Get(cpr::Url{"https://cataas.com/cat"});
|
||||
std::cout << "Fetching a cat: " << res.status_code << ", " << res.header["content-type"] << std::endl;
|
||||
bot->createMessage()
|
||||
->channel_id(*msg.channel_id)
|
||||
->filename("cat.jpg")
|
||||
->filetype(res.header["content-type"])
|
||||
->file(res.text)
|
||||
->run();
|
||||
});
|
||||
|
||||
bot->respond("channelinfo", [&bot](dpp::MessageCreateEvent msg) {
|
||||
bot->getChannel()
|
||||
->channel_id(*msg.channel_id)
|
||||
->onRead([&bot, msg](bool error, json res) {
|
||||
bot->createMessage()
|
||||
->channel_id(*msg.channel_id)
|
||||
->content("```json\n" + res["body"].dump(4) + "\n```")
|
||||
->run();
|
||||
})
|
||||
->run();
|
||||
});
|
||||
|
||||
bot->respond("register", [&bot, &self](dpp::MessageCreateEvent msg) {
|
||||
if (*msg.author->id == 272712928074006528) {
|
||||
bot->createGuildApplicationCommand()
|
||||
->application_id(*self.id)
|
||||
->guild_id(*msg.guild_id)
|
||||
->name("echo")
|
||||
->description("Echoes what you say")
|
||||
->options({dpp::ApplicationCommandOption(
|
||||
dpp::ApplicationCommandOptionType::STRING,
|
||||
std::string("message"), dpp::omitted, std::string("The message to echo"),
|
||||
dpp::omitted, true)})
|
||||
->command_type(dpp::ApplicationCommandType::CHAT_INPUT)
|
||||
->onRead([](bool error, json res) {
|
||||
std::cout << res.dump(4) << std::endl;
|
||||
})
|
||||
->run();
|
||||
}
|
||||
|
||||
bot->createGuildApplicationCommand()
|
||||
->application_id(*self.id)
|
||||
->guild_id(*msg.guild_id)
|
||||
->name("lookatthis")
|
||||
->description("Help information")
|
||||
->options({dpp::ApplicationCommandOption(
|
||||
dpp::ApplicationCommandOptionType::STRING,
|
||||
std::string("message"), dpp::omitted, std::string("The message to echo"),
|
||||
dpp::omitted, true)})
|
||||
->command_type(dpp::ApplicationCommandType::CHAT_INPUT)
|
||||
->onRead([](bool error, json res) {
|
||||
std::cout << res.dump(4) << std::endl;
|
||||
})
|
||||
->run();
|
||||
|
||||
});
|
||||
|
||||
bot->interactionHandlers.insert(
|
||||
{1102290596896460850, [&bot](dpp::Interaction msg) {
|
||||
bot->createResponse()
|
||||
->interaction_id(*msg.id)
|
||||
->interaction_token(*msg.token)
|
||||
->interaction_type(
|
||||
dpp::InteractionCallbackType::CHANNEL_MESSAGE_WITH_SOURCE)
|
||||
->data({{
|
||||
"content",
|
||||
*std::get<dpp::ApplicationCommandData>(*msg.data).options->at(0).value
|
||||
}})
|
||||
->run();
|
||||
}});
|
||||
|
||||
// Create handler for the MESSAGE_CREATE payload, this receives all messages
|
||||
// sent that the bot can see.
|
||||
bot->handlers.insert(
|
||||
{"MESSAGE_CREATE", [&bot, &self](const dpp::MessageCreateEvent msg) {
|
||||
// Ignore messages from other bots
|
||||
if (msg.webhook_id || (msg.author->bot && *msg.author->bot)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scan through mentions in the message for self
|
||||
bool mentioned = false;
|
||||
for (const dpp::User &mention : *msg.mentions) {
|
||||
mentioned = mentioned || (*mention.id == *self.id);
|
||||
}
|
||||
if (mentioned) {
|
||||
// Identify and remove mentions of self from the message
|
||||
std::stringstream content;
|
||||
content << "чё тебе надо, ";//*msg.content;
|
||||
/*unsigned int oldlength, length = content.length();
|
||||
do {
|
||||
oldlength = length;
|
||||
content = std::regex_replace(
|
||||
content,
|
||||
std::regex(R"(<@!?)" + std::to_string(*self.id) +
|
||||
R"(> ?)"),
|
||||
"");
|
||||
length = content.length();
|
||||
} while (oldlength > length);
|
||||
*/
|
||||
// Get the target user's display name
|
||||
std::string name = *(msg.member->nick ? msg.member->nick
|
||||
: msg.author->username);
|
||||
content << name << "?";
|
||||
//std::cout << "Echoing " << name << '\n';
|
||||
|
||||
// Echo the created message
|
||||
bot->createMessage()
|
||||
->channel_id(*msg.channel_id)
|
||||
->content(content.str())
|
||||
->run();
|
||||
|
||||
// Set status to Playing "with [author]"
|
||||
/*bot->send(3,
|
||||
{{"game", {{"name", "with " + name}, {"type", 0}}},
|
||||
{"status", "online"},
|
||||
{"afk", false},
|
||||
{"since", "null"}});*/
|
||||
}
|
||||
}});
|
||||
|
||||
|
||||
auto asioCtx = std::make_shared<asio::io_context>();
|
||||
|
||||
bot->initBot(9, token, asioCtx);
|
||||
bot->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
74
source/utils.hpp
Normal file
74
source/utils.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
/*/
|
||||
* Source: https://stackoverflow.com/a/6089413/1526048
|
||||
/*/
|
||||
std::istream &safeGetline(std::istream& is, std::string& str)
|
||||
{
|
||||
str.clear();
|
||||
|
||||
// The characters in the stream are read one-by-one using a std::streambuf.
|
||||
// That is faster than reading them one-by-one using the std::istream.
|
||||
// Code that uses streambuf this way must be guarded by a sentry object.
|
||||
// The sentry object performs various tasks,
|
||||
// such as thread synchronization and updating the stream state.
|
||||
|
||||
std::istream::sentry se(is, true);
|
||||
std::streambuf *sb = is.rdbuf();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int c = sb->sbumpc();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
return is;
|
||||
|
||||
case '\r':
|
||||
if (sb->sgetc() == '\n') {
|
||||
sb->sbumpc();
|
||||
}
|
||||
return is;
|
||||
|
||||
case std::streambuf::traits_type::eof():
|
||||
// Also handle the case when the last line has no line ending
|
||||
if (str.empty())
|
||||
is.setstate(std::ios::eofbit);
|
||||
|
||||
return is;
|
||||
|
||||
default:
|
||||
str += (char)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string getToken(const std::string& filename = "")
|
||||
{
|
||||
std::string token;
|
||||
char const *env = std::getenv("BOT_TOKEN");
|
||||
|
||||
if (env != nullptr)
|
||||
{
|
||||
token = std::string(env);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ifstream tokenFile(filename);
|
||||
|
||||
if (!tokenFile)
|
||||
return "";
|
||||
|
||||
safeGetline(tokenFile, token);
|
||||
tokenFile.close();
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user