Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F140331
power-levels-desc.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
power-levels-desc.cpp
View Options
/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include
<libkazv-config.hpp>
#include
<event.hpp>
#include
"validator.hpp"
#include
"power-levels-desc.hpp"
namespace
Kazv
{
static
std
::
pair
<
bool
,
json
>
numericValidator
(
const
json
&
j
)
{
if
(
j
.
is_number
())
{
return
{
true
,
json
(
j
.
template
get
<
long
long
>
())};
}
else
if
(
j
.
is_string
())
{
auto
str
=
j
.
template
get
<
std
::
string
>
();
try
{
std
::
size_t
pos
=
0
;
auto
num
=
std
::
stoll
(
str
,
&
pos
);
if
(
pos
!=
str
.
size
())
{
// not entirely a number
return
{
false
,
json
()};
}
return
{
true
,
json
(
num
)};
}
catch
(
const
std
::
logic_error
&
)
{
return
{
false
,
json
()};
}
}
else
{
return
{
false
,
json
()};
}
}
static
std
::
pair
<
bool
,
json
>
eventsValidator
(
const
json
&
j
)
{
auto
[
ret
,
val
]
=
numericValidator
(
j
[
1
]);
return
{
ret
,
json
::
array
({
j
[
0
],
std
::
move
(
val
)})};
}
static
std
::
pair
<
bool
,
json
>
notificationsValidator
(
const
json
&
j
)
{
auto
ret
=
json
::
object
();
auto
res
=
cast
(
ret
,
j
,
"room"
,
numericValidator
);
return
{
res
,
ret
};
}
static
std
::
pair
<
bool
,
json
>
usersValidator
(
const
json
&
j
)
{
auto
[
ret
,
val
]
=
numericValidator
(
j
[
1
]);
return
{
ret
,
json
::
array
({
j
[
0
],
std
::
move
(
val
)})};
}
// https://spec.matrix.org/v1.8/client-server-api/#mroompower_levels
static
const
auto
numericFields
=
immer
::
map
<
std
::
string
,
long
long
>
{
{
"ban"
,
50
},
{
"events_default"
,
0
},
{
"invite"
,
0
},
{
"kick"
,
50
},
{
"redact"
,
50
},
{
"state_default"
,
50
},
{
"users_default"
,
0
},
};
struct
PowerLevelsDesc
::
Private
{
Private
(
const
Event
&
e
)
:
original
(
e
)
,
normalized
(
normalize
(
e
))
{}
Event
normalize
(
const
Event
&
e
)
{
auto
content
=
e
.
content
().
get
();
auto
ret
=
json
{
{
"type"
,
"m.power_levels"
},
{
"state_key"
,
""
},
{
"content"
,
json
::
object
()},
};
// cast numeric fields
for
(
const
auto
&
[
key
,
defaultValue
]
:
numericFields
)
{
ret
[
"content"
][
key
]
=
defaultValue
;
cast
(
ret
[
"content"
],
content
,
key
,
numericValidator
);
}
// cast events map
ret
[
"content"
][
"events"
]
=
json
::
object
();
castObject
(
ret
[
"content"
],
content
,
"events"
,
eventsValidator
,
CastObjectStrategy
::
IgnoreInvalid
);
// cast notifications map
cast
(
ret
[
"content"
],
content
,
"notifications"
,
notificationsValidator
);
// cast users map
ret
[
"content"
][
"users"
]
=
json
::
object
();
castObject
(
ret
[
"content"
],
content
,
"users"
,
usersValidator
,
CastObjectStrategy
::
IgnoreInvalid
);
return
Event
(
ret
);
}
template
<
class
Key
>
static
void
setInContent
(
json
&
j
,
Key
&&
k
,
std
::
optional
<
PowerLevel
>
value
)
{
if
(
!
j
[
"content"
].
is_object
())
{
j
[
"content"
]
=
json
::
object
();
}
if
(
value
.
has_value
())
{
j
[
"content"
][
std
::
forward
<
Key
>
(
k
)]
=
value
.
value
();
}
else
{
j
[
"content"
].
erase
(
std
::
forward
<
Key
>
(
k
));
}
}
Event
original
;
Event
normalized
;
};
PowerLevelsDesc
::
PowerLevelsDesc
(
const
Event
&
e
)
:
m_d
(
new
Private
(
e
))
{}
PowerLevelsDesc
::~
PowerLevelsDesc
()
=
default
;
KAZV_DEFINE_COPYABLE_UNIQUE_PTR
(
PowerLevelsDesc
,
m_d
);
PowerLevel
PowerLevelsDesc::powerLevelOfUser
(
std
::
string
userId
)
const
{
const
auto
content
=
m_d
->
normalized
.
content
().
get
();
if
(
content
[
"users"
].
contains
(
userId
))
{
return
content
[
"users"
][
userId
].
template
get
<
PowerLevel
>
();
}
else
{
return
content
[
"users_default"
].
template
get
<
PowerLevel
>
();
}
}
bool
PowerLevelsDesc::canSendMessage
(
std
::
string
userId
,
std
::
string
eventType
)
const
{
auto
userPowerLevels
=
powerLevelOfUser
(
userId
);
const
auto
content
=
m_d
->
normalized
.
content
().
get
();
auto
powerLevelsNeeded
=
content
[
"events"
].
contains
(
eventType
)
?
content
[
"events"
][
eventType
].
template
get
<
PowerLevel
>
()
:
content
[
"events_default"
].
template
get
<
PowerLevel
>
();
return
userPowerLevels
>=
powerLevelsNeeded
;
}
bool
PowerLevelsDesc::canSendState
(
std
::
string
userId
,
std
::
string
eventType
)
const
{
auto
userPowerLevels
=
powerLevelOfUser
(
userId
);
const
auto
content
=
m_d
->
normalized
.
content
().
get
();
auto
powerLevelsNeeded
=
content
[
"events"
].
contains
(
eventType
)
?
content
[
"events"
][
eventType
].
template
get
<
PowerLevel
>
()
:
content
[
"state_default"
].
template
get
<
PowerLevel
>
();
return
userPowerLevels
>=
powerLevelsNeeded
;
}
bool
PowerLevelsDesc::canInvite
(
std
::
string
userId
)
const
{
auto
userPowerLevels
=
powerLevelOfUser
(
userId
);
const
auto
content
=
m_d
->
normalized
.
content
().
get
();
auto
powerLevelsNeeded
=
content
[
"invite"
].
template
get
<
PowerLevel
>
();
return
userPowerLevels
>=
powerLevelsNeeded
;
}
bool
PowerLevelsDesc::canKick
(
std
::
string
userId
)
const
{
auto
userPowerLevels
=
powerLevelOfUser
(
userId
);
const
auto
content
=
m_d
->
normalized
.
content
().
get
();
auto
powerLevelsNeeded
=
content
[
"kick"
].
template
get
<
PowerLevel
>
();
return
userPowerLevels
>=
powerLevelsNeeded
;
}
bool
PowerLevelsDesc::canBan
(
std
::
string
userId
)
const
{
auto
userPowerLevels
=
powerLevelOfUser
(
userId
);
const
auto
content
=
m_d
->
normalized
.
content
().
get
();
auto
powerLevelsNeeded
=
content
[
"ban"
].
template
get
<
PowerLevel
>
();
return
userPowerLevels
>=
powerLevelsNeeded
;
}
bool
PowerLevelsDesc::canRedact
(
std
::
string
userId
)
const
{
auto
userPowerLevels
=
powerLevelOfUser
(
userId
);
const
auto
content
=
m_d
->
normalized
.
content
().
get
();
auto
powerLevelsNeeded
=
content
[
"redact"
].
template
get
<
PowerLevel
>
();
return
userPowerLevels
>=
powerLevelsNeeded
;
}
Event
PowerLevelsDesc::normalizedEvent
()
const
{
return
m_d
?
m_d
->
normalized
:
Event
();
}
Event
PowerLevelsDesc::originalEvent
()
const
{
return
m_d
?
m_d
->
original
:
Event
();
}
PowerLevelsDesc
PowerLevelsDesc::setBan
(
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
m_d
->
setInContent
(
e
,
"ban"
,
powerLevel
);
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setKick
(
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
m_d
->
setInContent
(
e
,
"kick"
,
powerLevel
);
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setInvite
(
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
m_d
->
setInContent
(
e
,
"invite"
,
powerLevel
);
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setRedact
(
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
m_d
->
setInContent
(
e
,
"redact"
,
powerLevel
);
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setEventsDefault
(
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
m_d
->
setInContent
(
e
,
"events_default"
,
powerLevel
);
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setStateDefault
(
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
m_d
->
setInContent
(
e
,
"state_default"
,
powerLevel
);
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setUsersDefault
(
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
m_d
->
setInContent
(
e
,
"users_default"
,
powerLevel
);
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setUser
(
std
::
string
userId
,
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
e
.
merge_patch
(
json
{{
"content"
,
{
{
"users"
,
{
{
userId
,
powerLevel
?
json
(
powerLevel
.
value
())
:
json
(
nullptr
)}
}}}}});
return
PowerLevelsDesc
(
Event
(
e
));
}
PowerLevelsDesc
PowerLevelsDesc::setEvent
(
std
::
string
eventType
,
std
::
optional
<
PowerLevel
>
powerLevel
)
const
{
auto
e
=
m_d
->
original
.
originalJson
().
get
();
e
.
merge_patch
(
json
{{
"content"
,
{
{
"events"
,
{
{
eventType
,
powerLevel
?
json
(
powerLevel
.
value
())
:
json
(
nullptr
)}
}}}}});
return
PowerLevelsDesc
(
Event
(
e
));
}
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Jan 19, 6:06 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55367
Default Alt Text
power-levels-desc.cpp (8 KB)
Attached To
Mode
rL libkazv
Attached
Detach File
Event Timeline
Log In to Comment