Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if(CCACHE_PROGRAM)
endif()

project(libsession-util
VERSION 1.5.1
VERSION 1.6.0
DESCRIPTION "Session client utility library"
LANGUAGES ${LANGS})

Expand Down
2 changes: 1 addition & 1 deletion include/session/config/contacts.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ typedef struct contacts_contact {

int priority;
CONVO_NOTIFY_MODE notifications;
int64_t mute_until;
int64_t mute_until; // unix timestamp (seconds)

CONVO_EXPIRATION_MODE exp_mode;
int exp_seconds;
Expand Down
18 changes: 13 additions & 5 deletions include/session/config/contacts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,13 @@ struct contact_info {
// conversation is hidden. Otherwise (0) this is a regular, unpinned
// conversation.
notify_mode notifications = notify_mode::defaulted;
int64_t mute_until = 0; // If non-zero, disable notifications until the given unix timestamp
// (seconds, overriding whatever the current `notifications` value is
// until the timestamp expires).
std::chrono::sys_seconds mute_until{0s}; // If timestamp is non-zero, disable notifications
// until the given unix timestamp (seconds, overriding
// whatever the current `notifications` value is until
// the timestamp expires).
expiration_mode exp_mode = expiration_mode::none; // The expiry time; none if not expiring.
std::chrono::seconds exp_timer{0}; // The expiration timer (in seconds)
int64_t created = 0; // Unix timestamp (seconds) when this contact was added
std::chrono::sys_seconds created{0s}; // Unix timestamp (seconds) when this contact was added

explicit contact_info(std::string sid);

Expand Down Expand Up @@ -384,7 +385,14 @@ class Contacts : public ConfigBase {
/// Inputs:
/// - `session_id` -- hex string of the session id
/// - `timestamp` -- standard unix timestamp of the time contact was created
void set_created(std::string_view session_id, int64_t timestamp);
void set_created(std::string_view session_id, std::chrono::sys_seconds timestamp);

/// Deprecated: takes timestamp as an integer and guess whether it is seconds, milliseconds, or
/// microseconds.
[[deprecated(
"pass a std::chrono::sys_seconds instead (perhaps using "
"session::to_sys_seconds)")]] void
set_created(std::string_view session_id, int64_t timestamp);

/// API: contacts/contacts::erase
///
Expand Down
2 changes: 1 addition & 1 deletion include/session/config/convo_info_volatile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class val_loader;
namespace convo {

struct base {
int64_t last_read = 0;
sys_milliseconds last_read{};
bool unread = false;

protected:
Expand Down
41 changes: 25 additions & 16 deletions include/session/config/groups/info.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <chrono>
#include <memory>
#include <session/config.hpp>

#include "../base.hpp"
Expand Down Expand Up @@ -220,7 +219,11 @@ class Info : public ConfigBase {
/// Inputs:
/// - `session_id` -- hex string of the session id
/// - `timestamp` -- standard unix timestamp when the group was created
void set_created(int64_t timestamp);
void set_created(std::chrono::sys_seconds timestamp);
/// Deprecated version that attempts to guess whether the input is seconds, milliseconds, or
/// microseconds.
[[deprecated("pass a std::chrono::sys_seconds instead (or use session::to_sys_seconds)")]] void
set_created(int64_t timestamp);

/// API: groups/Info::get_created
///
Expand All @@ -229,23 +232,24 @@ class Info : public ConfigBase {
/// Inputs: none.
///
/// Outputs:
/// - `std::optional<int64_t>` -- the unix timestamp when the group was created, or nullopt if
/// the creation timestamp is not set.
std::optional<int64_t> get_created() const;
/// - `std::chrono::sys_seconds` -- the unix timestamp when the group was
/// created, or nullopt if the creation timestamp is not set.
std::optional<std::chrono::sys_seconds> get_created() const;

/// API: groups/Info::set_delete_before
///
/// Sets a "delete before" unix timestamp: this instructs clients to delete all messages from
/// the closed group history with a timestamp earlier than this value. Returns nullopt if no
/// delete-before timestamp is set.
///
/// The given value is checked for sanity (e.g. if you pass milliseconds it will be
/// interpreted as such)
///
/// Inputs:
/// - `timestamp` -- the new unix timestamp before which clients should delete messages. Pass 0
/// (or negative) to disable the delete-before timestamp.
void set_delete_before(int64_t timestamp);
void set_delete_before(std::chrono::sys_seconds timestamp);
/// Deprecated version that attempts to guess whether you meant seconds, milliseconds, or
/// microseconds.
[[deprecated("pass a std::chrono::sys_seconds instead (or use session::to_sys_seconds)")]] void
set_delete_before(int64_t timestamp);

/// API: groups/Info::get_delete_before
///
Expand All @@ -257,8 +261,9 @@ class Info : public ConfigBase {
/// Inputs: none.
///
/// Outputs:
/// - `int64_t` -- the unix timestamp for which all older messages shall be delete
std::optional<int64_t> get_delete_before() const;
/// - `sys_seconds` -- the unix timestamp for which all older messages shall be deleted, or
/// nullopt if there is no delete-before timestamp set.
std::optional<std::chrono::sys_seconds> get_delete_before() const;

/// API: groups/Info::set_delete_attach_before
///
Expand All @@ -272,9 +277,12 @@ class Info : public ConfigBase {
///
/// Inputs:
/// - `timestamp` -- the new unix timestamp before which clients should delete attachments. Pass
/// 0
/// (or negative) to disable the delete-attachment-before timestamp.
void set_delete_attach_before(int64_t timestamp);
/// 0 (or negative) to disable the delete-attachment-before timestamp.
void set_delete_attach_before(std::chrono::sys_seconds timestamp);
/// Deprecated version that attempts to guess whether you meant seconds, milliseconds, or
/// microseconds.
[[deprecated("pass a std::chrono::sys_seconds instead (or use session::to_sys_seconds)")]] void
set_delete_attach_before(int64_t timestamp);

/// API: groups/Info::get_delete_attach_before
///
Expand All @@ -286,8 +294,9 @@ class Info : public ConfigBase {
/// Inputs: none.
///
/// Outputs:
/// - `int64_t` -- the unix timestamp for which all older message attachments shall be deleted
std::optional<int64_t> get_delete_attach_before() const;
/// - `sys_seconds` -- the unix timestamp for which all older message attachments shall be
/// deleted, or nullopt if delete-attach-before is not enabled.
std::optional<std::chrono::sys_seconds> get_delete_attach_before() const;

/// API: groups/Info::destroy_group
///
Expand Down
1 change: 0 additions & 1 deletion include/session/config/user_groups.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ extern "C" {

#include "base.h"
#include "notify.h"
#include "util.h"

// Maximum length of a group name, in bytes
LIBSESSION_EXPORT extern const size_t GROUP_NAME_MAX_LENGTH;
Expand Down
10 changes: 6 additions & 4 deletions include/session/config/user_groups.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@ namespace session::config {
struct base_group_info {
static constexpr size_t NAME_MAX_LENGTH = 100; // in bytes; name will be truncated if exceeded

int priority = 0; // The priority; 0 means unpinned, -1 means hidden, positive means
// pinned higher (i.e. higher priority conversations come first).
int64_t joined_at = 0; // unix timestamp (seconds) when the group was joined (or re-joined)
int priority = 0; // The priority; 0 means unpinned, -1 means hidden, positive means
// pinned higher (i.e. higher priority conversations come first).
std::chrono::sys_seconds joined_at{}; // unix timestamp (seconds) when the group
// was joined (or re-joined)
notify_mode notifications = notify_mode::defaulted; // When the user wants notifications
int64_t mute_until = 0; // unix timestamp (seconds) until which notifications are disabled
std::chrono::sys_seconds mute_until{}; // unix timestamp (seconds) until which
// notifications are disabled

std::string name; // human-readable; always set for a legacy closed group, only used before
// joining a new closed group (after joining the group info provide the name)
Expand Down
14 changes: 7 additions & 7 deletions include/session/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,7 @@ inline std::string utf8_truncate(std::string val, size_t n) {
return val;
}

// Helper function to transform a timestamp provided in seconds, milliseconds or microseconds to
// seconds
inline int64_t to_epoch_seconds(int64_t timestamp) {
return timestamp > 9'000'000'000'000 ? timestamp / 1'000'000
: timestamp > 9'000'000'000 ? timestamp / 1'000
: timestamp;
}
using sys_milliseconds = std::chrono::sys_time<std::chrono::milliseconds>;

// Takes a timestamp as unix epoch seconds (not ms, µs) and wraps it in a sys_seconds containing it.
inline std::chrono::sys_seconds as_sys_seconds(int64_t timestamp) {
Expand All @@ -276,4 +270,10 @@ static_assert(std::is_same_v<
std::chrono::seconds,
decltype(std::declval<std::chrono::sys_seconds>().time_since_epoch())>);

// Takes a timestamp as unix epoch milliseconds (not seconds, or microseconds) and wraps it in a
// sys_ms containing it.
inline sys_milliseconds as_sys_ms(int64_t timestamp) {
return sys_milliseconds{std::chrono::milliseconds{timestamp}};
}

} // namespace session
25 changes: 15 additions & 10 deletions src/config/contacts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <oxenc/hex.h>
#include <sodium/crypto_generichash_blake2b.h>

#include <chrono>
#include <oxen/log.hpp>
#include <oxen/log/format.hpp>
#include <variant>
Expand Down Expand Up @@ -92,7 +93,9 @@ void contact_info::load(const dict& info_dict) {
} else {
notifications = notify_mode::defaulted;
}
mute_until = to_epoch_seconds(int_or_0(info_dict, "!"));
// Older client versions might have accidentally stored this as ms, so run it through
// to_sys_seconds:
mute_until = to_sys_seconds(int_or_0(info_dict, "!"));

int exp_mode_ = int_or_0(info_dict, "e");
if (exp_mode_ >= static_cast<int>(expiration_mode::none) &&
Expand All @@ -113,7 +116,9 @@ void contact_info::load(const dict& info_dict) {
}
}

created = to_epoch_seconds(int_or_0(info_dict, "j"));
// Older client versions might have accidentally stored this as ms, so run it through
// to_sys_seconds:
created = to_sys_seconds(int_or_0(info_dict, "j"));
}

void contact_info::into(contacts_contact& c) const {
Expand All @@ -132,12 +137,12 @@ void contact_info::into(contacts_contact& c) const {
c.blocked = blocked;
c.priority = priority;
c.notifications = static_cast<CONVO_NOTIFY_MODE>(notifications);
c.mute_until = to_epoch_seconds(mute_until);
c.mute_until = mute_until.time_since_epoch().count();
c.exp_mode = static_cast<CONVO_EXPIRATION_MODE>(exp_mode);
c.exp_seconds = exp_timer.count();
if (c.exp_seconds <= 0 && c.exp_mode != CONVO_EXPIRATION_NONE)
c.exp_mode = CONVO_EXPIRATION_NONE;
c.created = to_epoch_seconds(created);
c.created = created.time_since_epoch().count();
}

contact_info::contact_info(const contacts_contact& c) : session_id{c.session_id, 66} {
Expand All @@ -156,12 +161,12 @@ contact_info::contact_info(const contacts_contact& c) : session_id{c.session_id,
blocked = c.blocked;
priority = c.priority;
notifications = static_cast<notify_mode>(c.notifications);
mute_until = to_epoch_seconds(c.mute_until);
mute_until = to_sys_seconds(c.mute_until);
exp_mode = static_cast<expiration_mode>(c.exp_mode);
exp_timer = exp_mode == expiration_mode::none ? 0s : std::chrono::seconds{c.exp_seconds};
if (exp_timer <= 0s && exp_mode != expiration_mode::none)
exp_mode = expiration_mode::none;
created = to_epoch_seconds(c.created);
created = to_sys_seconds(c.created);
}

std::optional<contact_info> Contacts::get(std::string_view pubkey_hex) const {
Expand Down Expand Up @@ -211,7 +216,7 @@ void Contacts::set(const contact_info& contact) {
if (notify == notify_mode::mentions_only)
notify = notify_mode::all;
set_positive_int(info["@"], static_cast<int>(notify));
set_positive_int(info["!"], to_epoch_seconds(contact.mute_until));
set_ts(info["!"], contact.mute_until);

set_pair_if(
contact.exp_mode != expiration_mode::none && contact.exp_timer > 0s,
Expand All @@ -220,7 +225,7 @@ void Contacts::set(const contact_info& contact) {
info["E"],
contact.exp_timer.count());

set_positive_int(info["j"], to_epoch_seconds(contact.created));
set_ts(info["j"], contact.created);
}

void Contacts::set_name(std::string_view session_id, std::string name) {
Expand Down Expand Up @@ -285,9 +290,9 @@ void Contacts::set_expiry(
set(c);
}

void Contacts::set_created(std::string_view session_id, int64_t timestamp) {
void Contacts::set_created(std::string_view session_id, std::chrono::sys_seconds timestamp) {
auto c = get_or_construct(session_id);
c.created = to_epoch_seconds(timestamp);
c.created = timestamp;
set(c);
}

Expand Down
Loading