summaryrefslogtreecommitdiff
path: root/src/discord/snowflake.cpp
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2021-11-28 22:48:30 -0500
committerouwou <26526779+ouwou@users.noreply.github.com>2021-11-28 22:48:30 -0500
commite1703aea3fd597b23bde90e6c505278c517be611 (patch)
tree37d98fc90c9cd0844388bfb79beda2204f44af92 /src/discord/snowflake.cpp
parentfd53a76bf6f53a095a639765923a30f2206b2cd6 (diff)
parente02107feea8214a045e6faa969f00dcbc0d2b072 (diff)
downloadabaddon-portaudio-e1703aea3fd597b23bde90e6c505278c517be611.tar.gz
abaddon-portaudio-e1703aea3fd597b23bde90e6c505278c517be611.zip
merge master
Diffstat (limited to 'src/discord/snowflake.cpp')
-rw-r--r--src/discord/snowflake.cpp66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/discord/snowflake.cpp b/src/discord/snowflake.cpp
new file mode 100644
index 0000000..6909a15
--- /dev/null
+++ b/src/discord/snowflake.cpp
@@ -0,0 +1,66 @@
+#include "snowflake.hpp"
+#include <ctime>
+#include <iomanip>
+#include <chrono>
+#include <glibmm.h>
+
+constexpr static uint64_t DiscordEpochSeconds = 1420070400;
+
+const Snowflake Snowflake::Invalid = -1ULL;
+
+Snowflake::Snowflake()
+ : m_num(Invalid) {}
+
+Snowflake::Snowflake(uint64_t n)
+ : m_num(n) {}
+
+Snowflake::Snowflake(const std::string &str) {
+ if (str.size())
+ m_num = std::stoull(str);
+ else
+ m_num = Invalid;
+}
+Snowflake::Snowflake(const Glib::ustring &str) {
+ if (str.size())
+ m_num = std::strtoull(str.c_str(), nullptr, 10);
+ else
+ m_num = Invalid;
+};
+
+Snowflake Snowflake::FromNow() {
+ using namespace std::chrono;
+ // not guaranteed to work but it probably will anyway
+ static uint64_t counter = 0;
+ const auto millis_since_epoch = static_cast<uint64_t>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
+ const auto epoch = millis_since_epoch - DiscordEpochSeconds * 1000;
+ uint64_t snowflake = epoch << 22;
+ // worker id and process id would be OR'd in here but there's no point
+ snowflake |= counter++ % 4096;
+ return snowflake;
+}
+
+bool Snowflake::IsValid() const {
+ return m_num != Invalid;
+}
+
+Glib::ustring Snowflake::GetLocalTimestamp() const {
+ const time_t secs_since_epoch = (m_num / SecondsInterval) + DiscordEpochSeconds;
+ const std::tm tm = *localtime(&secs_since_epoch);
+ std::array<char, 256> tmp;
+ std::strftime(tmp.data(), sizeof(tmp), "%X %x", &tm);
+ return tmp.data();
+}
+
+void from_json(const nlohmann::json &j, Snowflake &s) {
+ if (j.is_string()) {
+ std::string tmp;
+ j.get_to(tmp);
+ s.m_num = std::stoull(tmp);
+ } else {
+ j.get_to(s.m_num);
+ }
+}
+
+void to_json(nlohmann::json &j, const Snowflake &s) {
+ j = std::to_string(s);
+}