mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Rules] Add rule to allow players to permanently save chat channels to database, up to a limit. (#2706)
* Initial code * Tweak * Rule description tweak * More channel work * More adjustments * Auto-join saved permanent player channels * Fix UCS crash if player has no channels to load from table. * Implemented channel blocking feature * Update database when player channel's owner or password change * First round of requested changes. * Logic tweak to ensure player channels are sets to permanent when appropraite * name_filter table integration and some refactoring * Use new `reserved_channel_names` table to block specific channel names. * Remove some legacy channel block code * Setup required SQL update to create `reserved_channel_names` table. * Update db_update_manifest.txt * Update db_update_manifest.txt * Update chatchannel.cpp * Code review * Database to UCSDatabase * Repository SaveChatChannel * CurrentPlayerChannelCount repository * Cleanup name filter * CreateChannel * Update websocketpp * Increment CURRENT_BINARY_DATABASE_VERSION Set to 9216 * Minor tweaks to blocked channel name checks & other related areas. - Enforce blocked channel names on channel creation. - Also enforce blocked channel names on channel join. - Add channel status check to Debug logging. - Minor formatting adjustments. - Add single quotes to column name value in query. * Minor log change * Increment DB Version * Formatting Tweaks - Made formatting adjustments consistent with KinglyKrab's recommended changes. - This compiles successfully with these changes, but unable to test the changes until this weekend. Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
parent
03a27b02ff
commit
29473aa7f5
@ -182,6 +182,8 @@ SET(repositories
|
|||||||
repositories/base/base_char_create_combinations_repository.h
|
repositories/base/base_char_create_combinations_repository.h
|
||||||
repositories/base/base_char_create_point_allocations_repository.h
|
repositories/base/base_char_create_point_allocations_repository.h
|
||||||
repositories/base/base_char_recipe_list_repository.h
|
repositories/base/base_char_recipe_list_repository.h
|
||||||
|
repositories/base/base_chatchannels_repository.h
|
||||||
|
repositories/base/base_chatchannel_reserved_names_repository.h
|
||||||
repositories/base/base_completed_shared_tasks_repository.h
|
repositories/base/base_completed_shared_tasks_repository.h
|
||||||
repositories/base/base_completed_shared_task_activity_state_repository.h
|
repositories/base/base_completed_shared_task_activity_state_repository.h
|
||||||
repositories/base/base_completed_shared_task_members_repository.h
|
repositories/base/base_completed_shared_task_members_repository.h
|
||||||
@ -358,6 +360,8 @@ SET(repositories
|
|||||||
repositories/char_create_combinations_repository.h
|
repositories/char_create_combinations_repository.h
|
||||||
repositories/char_create_point_allocations_repository.h
|
repositories/char_create_point_allocations_repository.h
|
||||||
repositories/char_recipe_list_repository.h
|
repositories/char_recipe_list_repository.h
|
||||||
|
repositories/chatchannels_repository.h
|
||||||
|
repositories/chatchannel_reserved_names_repository.h
|
||||||
repositories/completed_shared_tasks_repository.h
|
repositories/completed_shared_tasks_repository.h
|
||||||
repositories/completed_shared_task_activity_state_repository.h
|
repositories/completed_shared_task_activity_state_repository.h
|
||||||
repositories/completed_shared_task_members_repository.h
|
repositories/completed_shared_task_members_repository.h
|
||||||
|
|||||||
@ -0,0 +1,334 @@
|
|||||||
|
/**
|
||||||
|
* DO NOT MODIFY THIS FILE
|
||||||
|
*
|
||||||
|
* This repository was automatically generated and is NOT to be modified directly.
|
||||||
|
* Any repository modifications are meant to be made to the repository extending the base.
|
||||||
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
|
*
|
||||||
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
|
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
|
||||||
|
#define EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../../database.h"
|
||||||
|
#include "../../strings.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
|
class BaseChatchannelReservedNamesRepository {
|
||||||
|
public:
|
||||||
|
struct ChatchannelReservedNames {
|
||||||
|
int32_t id;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string PrimaryKey()
|
||||||
|
{
|
||||||
|
return std::string("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> Columns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> SelectColumns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string ColumnsRaw()
|
||||||
|
{
|
||||||
|
return std::string(Strings::Implode(", ", Columns()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string SelectColumnsRaw()
|
||||||
|
{
|
||||||
|
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string TableName()
|
||||||
|
{
|
||||||
|
return std::string("chatchannel_reserved_names");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseSelect()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"SELECT {} FROM {}",
|
||||||
|
SelectColumnsRaw(),
|
||||||
|
TableName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseInsert()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"INSERT INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChatchannelReservedNames NewEntity()
|
||||||
|
{
|
||||||
|
ChatchannelReservedNames e{};
|
||||||
|
|
||||||
|
e.id = 0;
|
||||||
|
e.name = "";
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChatchannelReservedNames GetChatchannelReservedNames(
|
||||||
|
const std::vector<ChatchannelReservedNames> &chatchannel_reserved_namess,
|
||||||
|
int chatchannel_reserved_names_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (auto &chatchannel_reserved_names : chatchannel_reserved_namess) {
|
||||||
|
if (chatchannel_reserved_names.id == chatchannel_reserved_names_id) {
|
||||||
|
return chatchannel_reserved_names;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChatchannelReservedNames FindOne(
|
||||||
|
Database& db,
|
||||||
|
int chatchannel_reserved_names_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
|
chatchannel_reserved_names_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
if (results.RowCount() == 1) {
|
||||||
|
ChatchannelReservedNames e{};
|
||||||
|
|
||||||
|
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||||
|
e.name = row[1] ? row[1] : "";
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DeleteOne(
|
||||||
|
Database& db,
|
||||||
|
int chatchannel_reserved_names_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
PrimaryKey(),
|
||||||
|
chatchannel_reserved_names_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int UpdateOne(
|
||||||
|
Database& db,
|
||||||
|
const ChatchannelReservedNames &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto columns = Columns();
|
||||||
|
|
||||||
|
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE {} SET {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
Strings::Implode(", ", v),
|
||||||
|
PrimaryKey(),
|
||||||
|
e.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChatchannelReservedNames InsertOne(
|
||||||
|
Database& db,
|
||||||
|
ChatchannelReservedNames e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseInsert(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results.Success()) {
|
||||||
|
e.id = results.LastInsertedID();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = NewEntity();
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int InsertMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<ChatchannelReservedNames> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseInsert(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<ChatchannelReservedNames> All(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<ChatchannelReservedNames> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{}",
|
||||||
|
BaseSelect()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
ChatchannelReservedNames e{};
|
||||||
|
|
||||||
|
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||||
|
e.name = row[1] ? row[1] : "";
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<ChatchannelReservedNames> GetWhere(Database& db, const std::string &where_filter)
|
||||||
|
{
|
||||||
|
std::vector<ChatchannelReservedNames> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} WHERE {}",
|
||||||
|
BaseSelect(),
|
||||||
|
where_filter
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
ChatchannelReservedNames e{};
|
||||||
|
|
||||||
|
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||||
|
e.name = row[1] ? row[1] : "";
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM {} WHERE {}",
|
||||||
|
TableName(),
|
||||||
|
where_filter
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Truncate(Database& db)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"TRUNCATE TABLE {}",
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64 GetMaxId(Database& db)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||||
|
PrimaryKey(),
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT COUNT(*) FROM {} {}",
|
||||||
|
TableName(),
|
||||||
|
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
|
||||||
364
common/repositories/base/base_chatchannels_repository.h
Normal file
364
common/repositories/base/base_chatchannels_repository.h
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
/**
|
||||||
|
* DO NOT MODIFY THIS FILE
|
||||||
|
*
|
||||||
|
* This repository was automatically generated and is NOT to be modified directly.
|
||||||
|
* Any repository modifications are meant to be made to the repository extending the base.
|
||||||
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
|
*
|
||||||
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
|
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_BASE_CHATCHANNELS_REPOSITORY_H
|
||||||
|
#define EQEMU_BASE_CHATCHANNELS_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../../database.h"
|
||||||
|
#include "../../strings.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
|
class BaseChatchannelsRepository {
|
||||||
|
public:
|
||||||
|
struct Chatchannels {
|
||||||
|
int32_t id;
|
||||||
|
std::string name;
|
||||||
|
std::string owner;
|
||||||
|
std::string password;
|
||||||
|
int32_t minstatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string PrimaryKey()
|
||||||
|
{
|
||||||
|
return std::string("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> Columns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"owner",
|
||||||
|
"password",
|
||||||
|
"minstatus",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> SelectColumns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"owner",
|
||||||
|
"password",
|
||||||
|
"minstatus",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string ColumnsRaw()
|
||||||
|
{
|
||||||
|
return std::string(Strings::Implode(", ", Columns()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string SelectColumnsRaw()
|
||||||
|
{
|
||||||
|
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string TableName()
|
||||||
|
{
|
||||||
|
return std::string("chatchannels");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseSelect()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"SELECT {} FROM {}",
|
||||||
|
SelectColumnsRaw(),
|
||||||
|
TableName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseInsert()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"INSERT INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Chatchannels NewEntity()
|
||||||
|
{
|
||||||
|
Chatchannels e{};
|
||||||
|
|
||||||
|
e.id = 0;
|
||||||
|
e.name = "";
|
||||||
|
e.owner = "";
|
||||||
|
e.password = "";
|
||||||
|
e.minstatus = 0;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Chatchannels GetChatchannels(
|
||||||
|
const std::vector<Chatchannels> &chatchannelss,
|
||||||
|
int chatchannels_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (auto &chatchannels : chatchannelss) {
|
||||||
|
if (chatchannels.id == chatchannels_id) {
|
||||||
|
return chatchannels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Chatchannels FindOne(
|
||||||
|
Database& db,
|
||||||
|
int chatchannels_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
|
chatchannels_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
if (results.RowCount() == 1) {
|
||||||
|
Chatchannels e{};
|
||||||
|
|
||||||
|
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||||
|
e.name = row[1] ? row[1] : "";
|
||||||
|
e.owner = row[2] ? row[2] : "";
|
||||||
|
e.password = row[3] ? row[3] : "";
|
||||||
|
e.minstatus = static_cast<int32_t>(atoi(row[4]));
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DeleteOne(
|
||||||
|
Database& db,
|
||||||
|
int chatchannels_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
PrimaryKey(),
|
||||||
|
chatchannels_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int UpdateOne(
|
||||||
|
Database& db,
|
||||||
|
const Chatchannels &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto columns = Columns();
|
||||||
|
|
||||||
|
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
|
||||||
|
v.push_back(columns[2] + " = '" + Strings::Escape(e.owner) + "'");
|
||||||
|
v.push_back(columns[3] + " = '" + Strings::Escape(e.password) + "'");
|
||||||
|
v.push_back(columns[4] + " = " + std::to_string(e.minstatus));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE {} SET {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
Strings::Implode(", ", v),
|
||||||
|
PrimaryKey(),
|
||||||
|
e.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Chatchannels InsertOne(
|
||||||
|
Database& db,
|
||||||
|
Chatchannels e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.owner) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.password) + "'");
|
||||||
|
v.push_back(std::to_string(e.minstatus));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseInsert(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results.Success()) {
|
||||||
|
e.id = results.LastInsertedID();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = NewEntity();
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int InsertMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<Chatchannels> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.owner) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.password) + "'");
|
||||||
|
v.push_back(std::to_string(e.minstatus));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseInsert(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<Chatchannels> All(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<Chatchannels> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{}",
|
||||||
|
BaseSelect()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
Chatchannels e{};
|
||||||
|
|
||||||
|
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||||
|
e.name = row[1] ? row[1] : "";
|
||||||
|
e.owner = row[2] ? row[2] : "";
|
||||||
|
e.password = row[3] ? row[3] : "";
|
||||||
|
e.minstatus = static_cast<int32_t>(atoi(row[4]));
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<Chatchannels> GetWhere(Database& db, const std::string &where_filter)
|
||||||
|
{
|
||||||
|
std::vector<Chatchannels> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} WHERE {}",
|
||||||
|
BaseSelect(),
|
||||||
|
where_filter
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
Chatchannels e{};
|
||||||
|
|
||||||
|
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||||
|
e.name = row[1] ? row[1] : "";
|
||||||
|
e.owner = row[2] ? row[2] : "";
|
||||||
|
e.password = row[3] ? row[3] : "";
|
||||||
|
e.minstatus = static_cast<int32_t>(atoi(row[4]));
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM {} WHERE {}",
|
||||||
|
TableName(),
|
||||||
|
where_filter
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Truncate(Database& db)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"TRUNCATE TABLE {}",
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64 GetMaxId(Database& db)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||||
|
PrimaryKey(),
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT COUNT(*) FROM {} {}",
|
||||||
|
TableName(),
|
||||||
|
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BASE_CHATCHANNELS_REPOSITORY_H
|
||||||
50
common/repositories/chatchannel_reserved_names_repository.h
Normal file
50
common/repositories/chatchannel_reserved_names_repository.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
|
||||||
|
#define EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../database.h"
|
||||||
|
#include "../strings.h"
|
||||||
|
#include "base/base_chatchannel_reserved_names_repository.h"
|
||||||
|
|
||||||
|
class ChatchannelReservedNamesRepository: public BaseChatchannelReservedNamesRepository {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file was auto generated and can be modified and extended upon
|
||||||
|
*
|
||||||
|
* Base repository methods are automatically
|
||||||
|
* generated in the "base" version of this repository. The base repository
|
||||||
|
* is immutable and to be left untouched, while methods in this class
|
||||||
|
* are used as extension methods for more specific persistence-layer
|
||||||
|
* accessors or mutators.
|
||||||
|
*
|
||||||
|
* Base Methods (Subject to be expanded upon in time)
|
||||||
|
*
|
||||||
|
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||||
|
*
|
||||||
|
* InsertOne
|
||||||
|
* UpdateOne
|
||||||
|
* DeleteOne
|
||||||
|
* FindOne
|
||||||
|
* GetWhere(std::string where_filter)
|
||||||
|
* DeleteWhere(std::string where_filter)
|
||||||
|
* InsertMany
|
||||||
|
* All
|
||||||
|
*
|
||||||
|
* Example custom methods in a repository
|
||||||
|
*
|
||||||
|
* ChatchannelReservedNamesRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||||
|
* ChatchannelReservedNamesRepository::GetWhereNeverExpires()
|
||||||
|
* ChatchannelReservedNamesRepository::GetWhereXAndY()
|
||||||
|
* ChatchannelReservedNamesRepository::DeleteWhereXAndY()
|
||||||
|
*
|
||||||
|
* Most of the above could be covered by base methods, but if you as a developer
|
||||||
|
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||||
|
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||||
|
* method and encapsulate filters there
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Custom extended repository methods here
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H
|
||||||
50
common/repositories/chatchannels_repository.h
Normal file
50
common/repositories/chatchannels_repository.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef EQEMU_CHATCHANNELS_REPOSITORY_H
|
||||||
|
#define EQEMU_CHATCHANNELS_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../database.h"
|
||||||
|
#include "../strings.h"
|
||||||
|
#include "base/base_chatchannels_repository.h"
|
||||||
|
|
||||||
|
class ChatchannelsRepository: public BaseChatchannelsRepository {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file was auto generated and can be modified and extended upon
|
||||||
|
*
|
||||||
|
* Base repository methods are automatically
|
||||||
|
* generated in the "base" version of this repository. The base repository
|
||||||
|
* is immutable and to be left untouched, while methods in this class
|
||||||
|
* are used as extension methods for more specific persistence-layer
|
||||||
|
* accessors or mutators.
|
||||||
|
*
|
||||||
|
* Base Methods (Subject to be expanded upon in time)
|
||||||
|
*
|
||||||
|
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||||
|
*
|
||||||
|
* InsertOne
|
||||||
|
* UpdateOne
|
||||||
|
* DeleteOne
|
||||||
|
* FindOne
|
||||||
|
* GetWhere(std::string where_filter)
|
||||||
|
* DeleteWhere(std::string where_filter)
|
||||||
|
* InsertMany
|
||||||
|
* All
|
||||||
|
*
|
||||||
|
* Example custom methods in a repository
|
||||||
|
*
|
||||||
|
* ChatchannelsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||||
|
* ChatchannelsRepository::GetWhereNeverExpires()
|
||||||
|
* ChatchannelsRepository::GetWhereXAndY()
|
||||||
|
* ChatchannelsRepository::DeleteWhereXAndY()
|
||||||
|
*
|
||||||
|
* Most of the above could be covered by base methods, but if you as a developer
|
||||||
|
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||||
|
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||||
|
* method and encapsulate filters there
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Custom extended repository methods here
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_CHATCHANNELS_REPOSITORY_H
|
||||||
@ -625,6 +625,7 @@ RULE_BOOL(Chat, EnableVoiceMacros, true, "Enable voice macros")
|
|||||||
RULE_BOOL(Chat, EnableMailKeyIPVerification, true, "Setting whether the authenticity of the client should be verified via its IP address when accessing the InGame mailbox")
|
RULE_BOOL(Chat, EnableMailKeyIPVerification, true, "Setting whether the authenticity of the client should be verified via its IP address when accessing the InGame mailbox")
|
||||||
RULE_BOOL(Chat, EnableAntiSpam, true, "Enable anti-spam system for chat")
|
RULE_BOOL(Chat, EnableAntiSpam, true, "Enable anti-spam system for chat")
|
||||||
RULE_BOOL(Chat, SuppressCommandErrors, false, "Do not suppress command errors by default")
|
RULE_BOOL(Chat, SuppressCommandErrors, false, "Do not suppress command errors by default")
|
||||||
|
RULE_INT(Chat, MaxPermanentPlayerChannels, 0, "Maximum number of permanent chat channels a player can make. Default 0.")
|
||||||
RULE_INT(Chat, MinStatusToBypassAntiSpam, 100, "Minimum status to bypass the anti-spam system")
|
RULE_INT(Chat, MinStatusToBypassAntiSpam, 100, "Minimum status to bypass the anti-spam system")
|
||||||
RULE_INT(Chat, MinimumMessagesPerInterval, 4, "Minimum number of chat messages allowed per interval. The karma value is added to this value")
|
RULE_INT(Chat, MinimumMessagesPerInterval, 4, "Minimum number of chat messages allowed per interval. The karma value is added to this value")
|
||||||
RULE_INT(Chat, MaximumMessagesPerInterval, 12, "Maximum value of chat messages allowed per interval")
|
RULE_INT(Chat, MaximumMessagesPerInterval, 12, "Maximum value of chat messages allowed per interval")
|
||||||
|
|||||||
@ -34,7 +34,7 @@
|
|||||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9216
|
#define CURRENT_BINARY_DATABASE_VERSION 9217
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9035
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9035
|
||||||
|
|||||||
@ -33,33 +33,33 @@ void ServerToClient50SayLink(std::string& clientSayLink, const std::string& serv
|
|||||||
void ServerToClient55SayLink(std::string& clientSayLink, const std::string& serverSayLink);
|
void ServerToClient55SayLink(std::string& clientSayLink, const std::string& serverSayLink);
|
||||||
|
|
||||||
ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string inPassword, bool inPermanent, int inMinimumStatus) :
|
ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string inPassword, bool inPermanent, int inMinimumStatus) :
|
||||||
DeleteTimer(0) {
|
m_delete_timer(0) {
|
||||||
|
|
||||||
Name = inName;
|
m_name = inName;
|
||||||
|
|
||||||
Owner = inOwner;
|
m_owner = inOwner;
|
||||||
|
|
||||||
Password = inPassword;
|
m_password = inPassword;
|
||||||
|
|
||||||
Permanent = inPermanent;
|
m_permanent = inPermanent;
|
||||||
|
|
||||||
MinimumStatus = inMinimumStatus;
|
m_minimum_status = inMinimumStatus;
|
||||||
|
|
||||||
Moderated = false;
|
m_moderated = false;
|
||||||
|
|
||||||
LogDebug(
|
LogDebug(
|
||||||
"New ChatChannel created: Name: [[{}]], Owner: [[{}]], Password: [[{}]], MinStatus: [{}]",
|
"New ChatChannel created: Name: [{}], Owner: [{}], Password: [{}], MinStatus: [{}]",
|
||||||
Name.c_str(),
|
m_name.c_str(),
|
||||||
Owner.c_str(),
|
m_owner.c_str(),
|
||||||
Password.c_str(),
|
m_password.c_str(),
|
||||||
MinimumStatus
|
m_minimum_status
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatChannel::~ChatChannel() {
|
ChatChannel::~ChatChannel() {
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
@ -67,18 +67,79 @@ ChatChannel::~ChatChannel() {
|
|||||||
iterator.RemoveCurrent(false);
|
iterator.RemoveCurrent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatChannel* ChatChannelList::CreateChannel(std::string Name, std::string Owner, std::string Password, bool Permanent, int MinimumStatus) {
|
ChatChannel *ChatChannelList::CreateChannel(
|
||||||
|
const std::string& name,
|
||||||
|
const std::string& owner,
|
||||||
|
const std::string& password,
|
||||||
|
bool permanent,
|
||||||
|
int minimum_status,
|
||||||
|
bool save_to_db
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint8 max_perm_player_channels = RuleI(Chat, MaxPermanentPlayerChannels);
|
||||||
|
|
||||||
ChatChannel *NewChannel = new ChatChannel(CapitaliseName(Name), Owner, Password, Permanent, MinimumStatus);
|
if (!database.CheckChannelNameFilter(name)) {
|
||||||
|
if (!(owner == SYSTEM_OWNER)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogDebug("Ignoring Name Filter as channel is owned by System...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ChatChannels.Insert(NewChannel);
|
if (IsOnChannelBlockList(name)) {
|
||||||
|
if (!(owner == SYSTEM_OWNER)) {
|
||||||
|
LogInfo("Channel name [{}] is a reserved/blocked channel name. Channel creation canceled.", name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogInfo("Ignoring reserved/blocked channel name [{}] as channel is owned by System...", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogDebug("Channel name [{}] passed the reserved/blocked channel name check...", name);
|
||||||
|
}
|
||||||
|
|
||||||
return NewChannel;
|
|
||||||
|
auto *new_channel = new ChatChannel(CapitaliseName(name), owner, password, permanent, minimum_status);
|
||||||
|
|
||||||
|
ChatChannels.Insert(new_channel);
|
||||||
|
|
||||||
|
if (owner == SYSTEM_OWNER) {
|
||||||
|
save_to_db = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If permanent player channels are enabled (and not a system channel)
|
||||||
|
// save channel to database if not exceeding limit.
|
||||||
|
bool can_save_channel = (max_perm_player_channels > 0) && !(owner == SYSTEM_OWNER) && save_to_db;
|
||||||
|
if (can_save_channel) {
|
||||||
|
|
||||||
|
// Ensure there is room to save another chat channel to the database.
|
||||||
|
bool player_under_channel_limit = database.CurrentPlayerChannelCount(owner) + 1 <= max_perm_player_channels;
|
||||||
|
if (player_under_channel_limit) {
|
||||||
|
database.SaveChatChannel(
|
||||||
|
CapitaliseName(name),
|
||||||
|
owner,
|
||||||
|
password,
|
||||||
|
minimum_status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogDebug(
|
||||||
|
"Maximum number of channels [{}] reached for player [{}], channel [{}] save to database aborted.",
|
||||||
|
max_perm_player_channels,
|
||||||
|
owner,
|
||||||
|
CapitaliseName(name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatChannel* ChatChannelList::FindChannel(std::string Name) {
|
ChatChannel* ChatChannelList::FindChannel(std::string Name) {
|
||||||
|
|
||||||
std::string NormalisedName = CapitaliseName(Name);
|
std::string normalized_name = CapitaliseName(Name);
|
||||||
|
|
||||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||||
|
|
||||||
@ -86,9 +147,9 @@ ChatChannel* ChatChannelList::FindChannel(std::string Name) {
|
|||||||
|
|
||||||
while(iterator.MoreElements()) {
|
while(iterator.MoreElements()) {
|
||||||
|
|
||||||
ChatChannel *CurrentChannel = iterator.GetData();
|
auto *current_channel = iterator.GetData();
|
||||||
|
|
||||||
if(CurrentChannel && (CurrentChannel->Name == NormalisedName))
|
if(current_channel && (current_channel->m_name == normalized_name))
|
||||||
return iterator.GetData();
|
return iterator.GetData();
|
||||||
|
|
||||||
iterator.Advance();
|
iterator.Advance();
|
||||||
@ -159,7 +220,7 @@ void ChatChannelList::SendAllChannels(Client *c) {
|
|||||||
|
|
||||||
void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
|
void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
|
||||||
|
|
||||||
LogDebug("RemoveChannel ([{}])", Channel->GetName().c_str());
|
LogDebug("Remove channel [{}]", Channel->GetName().c_str());
|
||||||
|
|
||||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||||
|
|
||||||
@ -194,7 +255,7 @@ int ChatChannel::MemberCount(int Status) {
|
|||||||
|
|
||||||
int Count = 0;
|
int Count = 0;
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
@ -211,30 +272,43 @@ int ChatChannel::MemberCount(int Status) {
|
|||||||
return Count;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::SetPassword(std::string inPassword) {
|
void ChatChannel::SetPassword(const std::string& in_password) {
|
||||||
|
|
||||||
Password = inPassword;
|
m_password = in_password;
|
||||||
|
|
||||||
if(Permanent)
|
if(m_permanent)
|
||||||
{
|
{
|
||||||
RemoveApostrophes(Password);
|
RemoveApostrophes(m_password);
|
||||||
database.SetChannelPassword(Name, Password);
|
database.SetChannelPassword(m_name, m_password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::SetOwner(std::string inOwner) {
|
void ChatChannel::SetOwner(std::string& in_owner) {
|
||||||
|
|
||||||
Owner = inOwner;
|
m_owner = in_owner;
|
||||||
|
|
||||||
if(Permanent)
|
if(m_permanent)
|
||||||
database.SetChannelOwner(Name, Owner);
|
database.SetChannelOwner(m_name, m_owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the owner's name in type std::string()
|
||||||
|
std::string& ChatChannel::GetOwnerName() {
|
||||||
|
return m_owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatChannel::SetTemporary() {
|
||||||
|
m_permanent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatChannel::SetPermanent() {
|
||||||
|
m_permanent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::AddClient(Client *c) {
|
void ChatChannel::AddClient(Client *c) {
|
||||||
|
|
||||||
if(!c) return;
|
if(!c) return;
|
||||||
|
|
||||||
DeleteTimer.Disable();
|
m_delete_timer.Disable();
|
||||||
|
|
||||||
if(IsClientInChannel(c)) {
|
if(IsClientInChannel(c)) {
|
||||||
|
|
||||||
@ -247,9 +321,9 @@ void ChatChannel::AddClient(Client *c) {
|
|||||||
|
|
||||||
int AccountStatus = c->GetAccountStatus();
|
int AccountStatus = c->GetAccountStatus();
|
||||||
|
|
||||||
LogDebug("Adding [{}] to channel [{}]", c->GetName().c_str(), Name.c_str());
|
LogDebug("Adding [{}] to channel [{}]", c->GetName().c_str(), m_name.c_str());
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
@ -264,7 +338,7 @@ void ChatChannel::AddClient(Client *c) {
|
|||||||
iterator.Advance();
|
iterator.Advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientsInChannel.Insert(c);
|
m_clients_in_channel.Insert(c);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,46 +346,46 @@ bool ChatChannel::RemoveClient(Client *c) {
|
|||||||
|
|
||||||
if(!c) return false;
|
if(!c) return false;
|
||||||
|
|
||||||
LogDebug("RemoveClient [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str());
|
LogDebug("Remove client [{}] from channel [{}]", c->GetName().c_str(), GetName().c_str());
|
||||||
|
|
||||||
bool HideMe = c->GetHideMe();
|
bool hide_me = c->GetHideMe();
|
||||||
|
|
||||||
int AccountStatus = c->GetAccountStatus();
|
int account_status = c->GetAccountStatus();
|
||||||
|
|
||||||
int PlayersInChannel = 0;
|
int players_in_channel = 0;
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
while(iterator.MoreElements()) {
|
while(iterator.MoreElements()) {
|
||||||
|
|
||||||
Client *CurrentClient = iterator.GetData();
|
auto *current_client = iterator.GetData();
|
||||||
|
|
||||||
if(CurrentClient == c) {
|
if(current_client == c) {
|
||||||
iterator.RemoveCurrent(false);
|
iterator.RemoveCurrent(false);
|
||||||
}
|
}
|
||||||
else if(CurrentClient) {
|
else if(current_client) {
|
||||||
|
|
||||||
PlayersInChannel++;
|
players_in_channel++;
|
||||||
|
|
||||||
if(CurrentClient->IsAnnounceOn())
|
if(current_client->IsAnnounceOn())
|
||||||
if(!HideMe || (CurrentClient->GetAccountStatus() > AccountStatus))
|
if(!hide_me || (current_client->GetAccountStatus() > account_status))
|
||||||
CurrentClient->AnnounceLeave(this, c);
|
current_client->AnnounceLeave(this, c);
|
||||||
|
|
||||||
iterator.Advance();
|
iterator.Advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((PlayersInChannel == 0) && !Permanent) {
|
if((players_in_channel == 0) && !m_permanent) {
|
||||||
|
|
||||||
if((Password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0))
|
if((m_password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
LogDebug("Starting delete timer for empty password protected channel [{}]", Name.c_str());
|
LogDebug("Starting delete timer for empty password protected channel [{}]", m_name.c_str());
|
||||||
|
|
||||||
DeleteTimer.Start(RuleI(Channels, DeleteTimer) * 60000);
|
m_delete_timer.Start(RuleI(Channels, DeleteTimer) * 60000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -322,9 +396,9 @@ void ChatChannel::SendOPList(Client *c)
|
|||||||
if (!c)
|
if (!c)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
c->GeneralChannelMessage("Channel " + Name + " op-list: (Owner=" + Owner + ")");
|
c->GeneralChannelMessage("Channel " + m_name + " op-list: (Owner=" + m_owner + ")");
|
||||||
|
|
||||||
for (auto &&m : Moderators)
|
for (auto &&m : m_moderators)
|
||||||
c->GeneralChannelMessage(m);
|
c->GeneralChannelMessage(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +424,7 @@ void ChatChannel::SendChannelMembers(Client *c) {
|
|||||||
|
|
||||||
int MembersInLine = 0;
|
int MembersInLine = 0;
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
@ -389,7 +463,7 @@ void ChatChannel::SendChannelMembers(Client *c) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
|
void ChatChannel::SendMessageToChannel(const std::string& Message, Client* Sender) {
|
||||||
|
|
||||||
if(!Sender) return;
|
if(!Sender) return;
|
||||||
|
|
||||||
@ -397,40 +471,40 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
|
|||||||
|
|
||||||
ChatMessagesSent++;
|
ChatMessagesSent++;
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
while(iterator.MoreElements()) {
|
while(iterator.MoreElements()) {
|
||||||
|
|
||||||
Client *ChannelClient = iterator.GetData();
|
auto *channel_client = iterator.GetData();
|
||||||
|
|
||||||
if(ChannelClient)
|
if(channel_client)
|
||||||
{
|
{
|
||||||
LogDebug("Sending message to [{}] from [{}]",
|
LogDebug("Sending message to [{}] from [{}]",
|
||||||
ChannelClient->GetName().c_str(), Sender->GetName().c_str());
|
channel_client->GetName().c_str(), Sender->GetName().c_str());
|
||||||
|
|
||||||
if (cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())].length() == 0) {
|
if (cv_messages[static_cast<uint32>(channel_client->GetClientVersion())].length() == 0) {
|
||||||
switch (ChannelClient->GetClientVersion()) {
|
switch (channel_client->GetClientVersion()) {
|
||||||
case EQ::versions::ClientVersion::Titanium:
|
case EQ::versions::ClientVersion::Titanium:
|
||||||
ServerToClient45SayLink(cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Message);
|
ServerToClient45SayLink(cv_messages[static_cast<uint32>(channel_client->GetClientVersion())], Message);
|
||||||
break;
|
break;
|
||||||
case EQ::versions::ClientVersion::SoF:
|
case EQ::versions::ClientVersion::SoF:
|
||||||
case EQ::versions::ClientVersion::SoD:
|
case EQ::versions::ClientVersion::SoD:
|
||||||
case EQ::versions::ClientVersion::UF:
|
case EQ::versions::ClientVersion::UF:
|
||||||
ServerToClient50SayLink(cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Message);
|
ServerToClient50SayLink(cv_messages[static_cast<uint32>(channel_client->GetClientVersion())], Message);
|
||||||
break;
|
break;
|
||||||
case EQ::versions::ClientVersion::RoF:
|
case EQ::versions::ClientVersion::RoF:
|
||||||
ServerToClient55SayLink(cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Message);
|
ServerToClient55SayLink(cv_messages[static_cast<uint32>(channel_client->GetClientVersion())], Message);
|
||||||
break;
|
break;
|
||||||
case EQ::versions::ClientVersion::RoF2:
|
case EQ::versions::ClientVersion::RoF2:
|
||||||
default:
|
default:
|
||||||
cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())] = Message;
|
cv_messages[static_cast<uint32>(channel_client->GetClientVersion())] = Message;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelClient->SendChannelMessage(Name, cv_messages[static_cast<uint32>(ChannelClient->GetClientVersion())], Sender);
|
channel_client->SendChannelMessage(m_name, cv_messages[static_cast<uint32>(channel_client->GetClientVersion())], Sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator.Advance();
|
iterator.Advance();
|
||||||
@ -439,9 +513,9 @@ void ChatChannel::SendMessageToChannel(std::string Message, Client* Sender) {
|
|||||||
|
|
||||||
void ChatChannel::SetModerated(bool inModerated) {
|
void ChatChannel::SetModerated(bool inModerated) {
|
||||||
|
|
||||||
Moderated = inModerated;
|
m_moderated = inModerated;
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
@ -451,10 +525,10 @@ void ChatChannel::SetModerated(bool inModerated) {
|
|||||||
|
|
||||||
if(ChannelClient) {
|
if(ChannelClient) {
|
||||||
|
|
||||||
if(Moderated)
|
if(m_moderated)
|
||||||
ChannelClient->GeneralChannelMessage("Channel " + Name + " is now moderated.");
|
ChannelClient->GeneralChannelMessage("Channel " + m_name + " is now moderated.");
|
||||||
else
|
else
|
||||||
ChannelClient->GeneralChannelMessage("Channel " + Name + " is no longer moderated.");
|
ChannelClient->GeneralChannelMessage("Channel " + m_name + " is no longer moderated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator.Advance();
|
iterator.Advance();
|
||||||
@ -465,7 +539,7 @@ bool ChatChannel::IsClientInChannel(Client *c) {
|
|||||||
|
|
||||||
if(!c) return false;
|
if(!c) return false;
|
||||||
|
|
||||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
LinkedListIterator<Client*> iterator(m_clients_in_channel);
|
||||||
|
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
@ -480,54 +554,80 @@ bool ChatChannel::IsClientInChannel(Client *c) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client *c) {
|
ChatChannel *ChatChannelList::AddClientToChannel(std::string channel_name, Client *c, bool command_directed) {
|
||||||
|
|
||||||
if(!c) return nullptr;
|
if(!c) return nullptr;
|
||||||
|
|
||||||
if((ChannelName.length() > 0) && (isdigit(ChannelName[0]))) {
|
if ((channel_name.length() > 0) && (isdigit(channel_name[0]))) { // Ensure channel name does not start with a number
|
||||||
|
|
||||||
c->GeneralChannelMessage("The channel name can not begin with a number.");
|
c->GeneralChannelMessage("The channel name can not begin with a number.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else if (channel_name.empty()) { // Ensure channel name is not empty
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NormalisedName, Password;
|
std::string normalized_name, password;
|
||||||
|
|
||||||
std::string::size_type Colon = ChannelName.find_first_of(":");
|
std::string::size_type Colon = channel_name.find_first_of(":");
|
||||||
|
|
||||||
if(Colon == std::string::npos)
|
if(Colon == std::string::npos)
|
||||||
NormalisedName = CapitaliseName(ChannelName);
|
normalized_name = CapitaliseName(channel_name);
|
||||||
else {
|
else {
|
||||||
NormalisedName = CapitaliseName(ChannelName.substr(0, Colon));
|
normalized_name = CapitaliseName(channel_name.substr(0, Colon));
|
||||||
|
|
||||||
Password = ChannelName.substr(Colon + 1);
|
password = channel_name.substr(Colon + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((NormalisedName.length() > 64) || (Password.length() > 64)) {
|
if((normalized_name.length() > 64) || (password.length() > 64)) {
|
||||||
|
|
||||||
c->GeneralChannelMessage("The channel name or password cannot exceed 64 characters.");
|
c->GeneralChannelMessage("The channel name or password cannot exceed 64 characters.");
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogDebug("AddClient to channel [[{}]] with password [[{}]]", NormalisedName.c_str(), Password.c_str());
|
ChatChannel *RequiredChannel = FindChannel(normalized_name);
|
||||||
|
|
||||||
ChatChannel *RequiredChannel = FindChannel(NormalisedName);
|
if (RequiredChannel) {
|
||||||
|
if (IsOnChannelBlockList(channel_name)) { // Ensure channel name is not blocked
|
||||||
|
if (!(RequiredChannel->GetOwnerName() == SYSTEM_OWNER)) {
|
||||||
|
c->GeneralChannelMessage("That channel name is blocked by the server operator.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogDebug("Reserved/blocked channel name check for [{}] ignored due to channel being owned by System...", normalized_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!RequiredChannel)
|
const std::string& channel_owner = c->GetName();
|
||||||
RequiredChannel = CreateChannel(NormalisedName, c->GetName(), Password, false, 0);
|
|
||||||
|
|
||||||
if(RequiredChannel->GetMinStatus() > c->GetAccountStatus()) {
|
bool permanent = false;
|
||||||
|
if (command_directed && RuleI(Chat, MaxPermanentPlayerChannels) > 0) {
|
||||||
|
permanent = true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Message = "You do not have the required account status to join channel " + NormalisedName;
|
if (!RequiredChannel) {
|
||||||
|
RequiredChannel = CreateChannel(normalized_name, channel_owner, password, permanent, 0, command_directed);
|
||||||
|
if (RequiredChannel == nullptr) {
|
||||||
|
LogDebug("Failed to create new channel with name: {}. Possible blocked or reserved channel name.", normalized_name);
|
||||||
|
c->GeneralChannelMessage("Failed to create new channel with provided name. Possible blocked or reserved channel name.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
LogDebug("Created and added Client to channel [{}] with password [{}]. Owner: {}. Command Directed: {}", normalized_name.c_str(), password.c_str(), channel_owner, command_directed);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogDebug("Checking status requirement of channel: {}. Channel status required: {}, player status: {}.", normalized_name, std::to_string(RequiredChannel->GetMinStatus()), std::to_string(c->GetAccountStatus()));
|
||||||
|
if (RequiredChannel->GetMinStatus() > c->GetAccountStatus()) {
|
||||||
|
std::string Message = "You do not have the required account status to join channel " + normalized_name;
|
||||||
|
|
||||||
c->GeneralChannelMessage(Message);
|
c->GeneralChannelMessage(Message);
|
||||||
|
LogInfo("Client [{}] connection to channel [{}] refused due to insufficient status.", c->GetName(), normalized_name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(RequiredChannel->IsClientInChannel(c))
|
if (RequiredChannel->IsClientInChannel(c)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if(RequiredChannel->IsInvitee(c->GetName())) {
|
if(RequiredChannel->IsInvitee(c->GetName())) {
|
||||||
|
|
||||||
@ -538,7 +638,7 @@ ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client
|
|||||||
return RequiredChannel;
|
return RequiredChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(RequiredChannel->CheckPassword(Password) || RequiredChannel->IsOwner(c->GetName()) || RequiredChannel->IsModerator(c->GetName()) ||
|
if(RequiredChannel->CheckPassword(password) || RequiredChannel->IsOwner(c->GetName()) || RequiredChannel->IsModerator(c->GetName()) ||
|
||||||
c->IsChannelAdmin()) {
|
c->IsChannelAdmin()) {
|
||||||
|
|
||||||
RequiredChannel->AddClient(c);
|
RequiredChannel->AddClient(c);
|
||||||
@ -546,32 +646,42 @@ ChatChannel *ChatChannelList::AddClientToChannel(std::string ChannelName, Client
|
|||||||
return RequiredChannel;
|
return RequiredChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->GeneralChannelMessage("Incorrect password for channel " + (NormalisedName));
|
c->GeneralChannelMessage("Incorrect password for channel " + (normalized_name));
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatChannel *ChatChannelList::RemoveClientFromChannel(std::string inChannelName, Client *c) {
|
ChatChannel *ChatChannelList::RemoveClientFromChannel(const std::string& in_channel_name, Client *c, bool command_directed) {
|
||||||
|
|
||||||
if(!c) return nullptr;
|
if(!c) return nullptr;
|
||||||
|
|
||||||
std::string ChannelName = inChannelName;
|
std::string channel_name = in_channel_name;
|
||||||
|
|
||||||
if((inChannelName.length() > 0) && isdigit(ChannelName[0]))
|
if (in_channel_name.length() > 0 && isdigit(channel_name[0])) {
|
||||||
ChannelName = c->ChannelSlotName(atoi(inChannelName.c_str()));
|
channel_name = c->ChannelSlotName(atoi(in_channel_name.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
ChatChannel *RequiredChannel = FindChannel(ChannelName);
|
auto *required_channel = FindChannel(channel_name);
|
||||||
|
|
||||||
if(!RequiredChannel)
|
if (!required_channel) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogDebug("Client [{}] removed from channel [{}]. Channel is owned by {}. Command directed: {}", c->GetName(), channel_name, required_channel->GetOwnerName(), command_directed);
|
||||||
|
if (c->GetName() == required_channel->GetOwnerName() && command_directed) { // Check if the client that is leaving is the the channel owner
|
||||||
|
LogDebug("Owner left the channel [{}], removing channel from database...", channel_name);
|
||||||
|
database.DeleteChatChannel(channel_name); // Remove the channel from the database.
|
||||||
|
LogDebug("Flagging [{}] channel as temporary...", channel_name);
|
||||||
|
required_channel->SetTemporary();
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveClient will return false if there is no-one left in the channel, and the channel is not permanent and has
|
// RemoveClient will return false if there is no-one left in the channel, and the channel is not permanent and has
|
||||||
// no password.
|
// no password.
|
||||||
//
|
if (!required_channel->RemoveClient(c)) {
|
||||||
if(!RequiredChannel->RemoveClient(c))
|
LogDebug("Noone left in the temporary channel [{}] and no password is set; removing temporary channel.", channel_name);
|
||||||
RemoveChannel(RequiredChannel);
|
RemoveChannel(required_channel);
|
||||||
|
}
|
||||||
|
|
||||||
return RequiredChannel;
|
return required_channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannelList::Process() {
|
void ChatChannelList::Process() {
|
||||||
@ -600,76 +710,76 @@ void ChatChannelList::Process() {
|
|||||||
void ChatChannel::AddInvitee(const std::string &Invitee)
|
void ChatChannel::AddInvitee(const std::string &Invitee)
|
||||||
{
|
{
|
||||||
if (!IsInvitee(Invitee)) {
|
if (!IsInvitee(Invitee)) {
|
||||||
Invitees.push_back(Invitee);
|
m_invitees.push_back(Invitee);
|
||||||
|
|
||||||
LogDebug("Added [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
|
LogDebug("Added [{}] as invitee to channel [{}]", Invitee.c_str(), m_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::RemoveInvitee(std::string Invitee)
|
void ChatChannel::RemoveInvitee(std::string Invitee)
|
||||||
{
|
{
|
||||||
auto it = std::find(std::begin(Invitees), std::end(Invitees), Invitee);
|
auto it = std::find(std::begin(m_invitees), std::end(m_invitees), Invitee);
|
||||||
|
|
||||||
if(it != std::end(Invitees)) {
|
if(it != std::end(m_invitees)) {
|
||||||
Invitees.erase(it);
|
m_invitees.erase(it);
|
||||||
LogDebug("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), Name.c_str());
|
LogDebug("Removed [{}] as invitee to channel [{}]", Invitee.c_str(), m_name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatChannel::IsInvitee(std::string Invitee)
|
bool ChatChannel::IsInvitee(std::string Invitee)
|
||||||
{
|
{
|
||||||
return std::find(std::begin(Invitees), std::end(Invitees), Invitee) != std::end(Invitees);
|
return std::find(std::begin(m_invitees), std::end(m_invitees), Invitee) != std::end(m_invitees);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::AddModerator(const std::string &Moderator)
|
void ChatChannel::AddModerator(const std::string &Moderator)
|
||||||
{
|
{
|
||||||
if (!IsModerator(Moderator)) {
|
if (!IsModerator(Moderator)) {
|
||||||
Moderators.push_back(Moderator);
|
m_moderators.push_back(Moderator);
|
||||||
|
|
||||||
LogInfo("Added [{}] as moderator to channel [{}]", Moderator.c_str(), Name.c_str());
|
LogInfo("Added [{}] as moderator to channel [{}]", Moderator.c_str(), m_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::RemoveModerator(const std::string &Moderator)
|
void ChatChannel::RemoveModerator(const std::string &Moderator)
|
||||||
{
|
{
|
||||||
auto it = std::find(std::begin(Moderators), std::end(Moderators), Moderator);
|
auto it = std::find(std::begin(m_moderators), std::end(m_moderators), Moderator);
|
||||||
|
|
||||||
if (it != std::end(Moderators)) {
|
if (it != std::end(m_moderators)) {
|
||||||
Moderators.erase(it);
|
m_moderators.erase(it);
|
||||||
LogInfo("Removed [{}] as moderator to channel [{}]", Moderator.c_str(), Name.c_str());
|
LogInfo("Removed [{}] as moderator to channel [{}]", Moderator.c_str(), m_name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatChannel::IsModerator(std::string Moderator)
|
bool ChatChannel::IsModerator(std::string Moderator)
|
||||||
{
|
{
|
||||||
return std::find(std::begin(Moderators), std::end(Moderators), Moderator) != std::end(Moderators);
|
return std::find(std::begin(m_moderators), std::end(m_moderators), Moderator) != std::end(m_moderators);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::AddVoice(const std::string &inVoiced)
|
void ChatChannel::AddVoice(const std::string &inVoiced)
|
||||||
{
|
{
|
||||||
if (!HasVoice(inVoiced)) {
|
if (!HasVoice(inVoiced)) {
|
||||||
Voiced.push_back(inVoiced);
|
m_voiced.push_back(inVoiced);
|
||||||
|
|
||||||
LogInfo("Added [{}] as voiced to channel [{}]", inVoiced.c_str(), Name.c_str());
|
LogInfo("Added [{}] as voiced to channel [{}]", inVoiced.c_str(), m_name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatChannel::RemoveVoice(const std::string &inVoiced)
|
void ChatChannel::RemoveVoice(const std::string &inVoiced)
|
||||||
{
|
{
|
||||||
auto it = std::find(std::begin(Voiced), std::end(Voiced), inVoiced);
|
auto it = std::find(std::begin(m_voiced), std::end(m_voiced), inVoiced);
|
||||||
|
|
||||||
if (it != std::end(Voiced)) {
|
if (it != std::end(m_voiced)) {
|
||||||
Voiced.erase(it);
|
m_voiced.erase(it);
|
||||||
|
|
||||||
LogInfo("Removed [{}] as voiced to channel [{}]", inVoiced.c_str(), Name.c_str());
|
LogInfo("Removed [{}] as voiced to channel [{}]", inVoiced.c_str(), m_name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatChannel::HasVoice(std::string inVoiced)
|
bool ChatChannel::HasVoice(std::string inVoiced)
|
||||||
{
|
{
|
||||||
return std::find(std::begin(Voiced), std::end(Voiced), inVoiced) != std::end(Voiced);
|
return std::find(std::begin(m_voiced), std::end(m_voiced), inVoiced) != std::end(m_voiced);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CapitaliseName(std::string inString) {
|
std::string CapitaliseName(std::string inString) {
|
||||||
@ -687,6 +797,31 @@ std::string CapitaliseName(std::string inString) {
|
|||||||
return NormalisedName;
|
return NormalisedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChatChannelList::IsOnChannelBlockList(const std::string& channel_name) {
|
||||||
|
if (channel_name.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if channel_name is already in the BlockedChannelNames vector
|
||||||
|
return Strings::Contains(ChatChannelList::GetBlockedChannelNames(), channel_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatChannelList::AddToChannelBlockList(const std::string& channel_name) {
|
||||||
|
if (channel_name.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if channelName is already in the BlockedChannelNames vector
|
||||||
|
bool is_found = Strings::Contains(ChatChannelList::GetBlockedChannelNames(), channel_name);
|
||||||
|
|
||||||
|
// Add channelName to the BlockedChannelNames vector if it is not already present
|
||||||
|
if (!is_found) {
|
||||||
|
auto blocked_channel_names = GetBlockedChannelNames(); // Get current blocked list
|
||||||
|
blocked_channel_names.push_back(channel_name); // Add new name to local blocked list
|
||||||
|
SetChannelBlockList(blocked_channel_names); // Set blocked list to match local blocked list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServerToClient45SayLink(std::string& clientSayLink, const std::string& serverSayLink) {
|
void ServerToClient45SayLink(std::string& clientSayLink, const std::string& serverSayLink) {
|
||||||
if (serverSayLink.find('\x12') == std::string::npos) {
|
if (serverSayLink.find('\x12') == std::string::npos) {
|
||||||
clientSayLink = serverSayLink;
|
clientSayLink = serverSayLink;
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
|
||||||
|
#define SYSTEM_OWNER std::string("*System*")
|
||||||
|
|
||||||
class ChatChannel {
|
class ChatChannel {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -21,15 +23,19 @@ public:
|
|||||||
bool IsClientInChannel(Client *c);
|
bool IsClientInChannel(Client *c);
|
||||||
|
|
||||||
int MemberCount(int Status);
|
int MemberCount(int Status);
|
||||||
const std::string &GetName() { return Name; }
|
const std::string &GetName() { return m_name; }
|
||||||
void SendMessageToChannel(std::string Message, Client* Sender);
|
void SendMessageToChannel(const std::string& Message, Client* Sender);
|
||||||
bool CheckPassword(std::string inPassword) { return Password.empty() || Password == inPassword; }
|
bool CheckPassword(const std::string& in_password) { return m_password.empty() || m_password == in_password; }
|
||||||
void SetPassword(std::string inPassword);
|
void SetPassword(const std::string& in_password);
|
||||||
bool IsOwner(std::string Name) { return (Owner == Name); }
|
bool IsOwner(const std::string& name) { return (m_owner == name); }
|
||||||
void SetOwner(std::string inOwner);
|
const std::string& GetPassword() { return m_password; }
|
||||||
|
void SetOwner(std::string& inOwner);
|
||||||
|
std::string& GetOwnerName();
|
||||||
|
void SetTemporary();
|
||||||
|
void SetPermanent();
|
||||||
void SendChannelMembers(Client *c);
|
void SendChannelMembers(Client *c);
|
||||||
int GetMinStatus() { return MinimumStatus; }
|
int GetMinStatus() { return m_minimum_status; }
|
||||||
bool ReadyToDelete() { return DeleteTimer.Check(); }
|
bool ReadyToDelete() { return m_delete_timer.Check(); }
|
||||||
void SendOPList(Client *c);
|
void SendOPList(Client *c);
|
||||||
void AddInvitee(const std::string &Invitee);
|
void AddInvitee(const std::string &Invitee);
|
||||||
void RemoveInvitee(std::string Invitee);
|
void RemoveInvitee(std::string Invitee);
|
||||||
@ -40,48 +46,52 @@ public:
|
|||||||
void AddVoice(const std::string &Voiced);
|
void AddVoice(const std::string &Voiced);
|
||||||
void RemoveVoice(const std::string &Voiced);
|
void RemoveVoice(const std::string &Voiced);
|
||||||
bool HasVoice(std::string Voiced);
|
bool HasVoice(std::string Voiced);
|
||||||
inline bool IsModerated() { return Moderated; }
|
inline bool IsModerated() { return m_moderated; }
|
||||||
void SetModerated(bool inModerated);
|
void SetModerated(bool inModerated);
|
||||||
|
|
||||||
friend class ChatChannelList;
|
friend class ChatChannelList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string Name;
|
std::string m_name;
|
||||||
std::string Owner;
|
std::string m_owner;
|
||||||
std::string Password;
|
std::string m_password;
|
||||||
|
|
||||||
bool Permanent;
|
bool m_permanent;
|
||||||
bool Moderated;
|
bool m_moderated;
|
||||||
|
|
||||||
int MinimumStatus;
|
int m_minimum_status;
|
||||||
|
|
||||||
Timer DeleteTimer;
|
Timer m_delete_timer;
|
||||||
|
|
||||||
LinkedList<Client*> ClientsInChannel;
|
LinkedList<Client*> m_clients_in_channel;
|
||||||
|
|
||||||
std::vector<std::string> Moderators;
|
std::vector<std::string> m_moderators;
|
||||||
std::vector<std::string> Invitees;
|
std::vector<std::string> m_invitees;
|
||||||
std::vector<std::string> Voiced;
|
std::vector<std::string> m_voiced;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChatChannelList {
|
class ChatChannelList {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChatChannel* CreateChannel(std::string Name, std::string Owner, std::string Passwordi, bool Permanent, int MinimumStatus = 0);
|
ChatChannel* CreateChannel(const std::string& name, const std::string& owner, const std::string& password, bool permanent, int minimum_status, bool save_to_database = false);
|
||||||
ChatChannel* FindChannel(std::string Name);
|
ChatChannel* FindChannel(std::string name);
|
||||||
ChatChannel* AddClientToChannel(std::string Channel, Client *c);
|
ChatChannel* AddClientToChannel(std::string channel_name, Client* c, bool command_directed = false);
|
||||||
ChatChannel* RemoveClientFromChannel(std::string Channel, Client *c);
|
ChatChannel* RemoveClientFromChannel(const std::string& in_channel_name, Client* c, bool command_directed = false);
|
||||||
void RemoveClientFromAllChannels(Client *c);
|
|
||||||
void RemoveChannel(ChatChannel *Channel);
|
void RemoveChannel(ChatChannel *Channel);
|
||||||
void RemoveAllChannels();
|
void RemoveAllChannels();
|
||||||
void SendAllChannels(Client *c);
|
void SendAllChannels(Client *c);
|
||||||
void Process();
|
void Process();
|
||||||
|
static inline std::vector<std::string> GetBlockedChannelNames() { return m_blocked_channel_names; }
|
||||||
|
static inline void ClearChannelBlockList() { m_blocked_channel_names.clear(); };
|
||||||
|
static void AddToChannelBlockList(const std::string& channel_name);
|
||||||
|
static bool IsOnChannelBlockList(const std::string& channel_name);
|
||||||
|
static inline void SetChannelBlockList(std::vector<std::string> new_list) { m_blocked_channel_names = new_list; }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
LinkedList<ChatChannel*> ChatChannels;
|
LinkedList<ChatChannel*> ChatChannels;
|
||||||
|
static inline std::vector<std::string> m_blocked_channel_names;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,10 @@ int LookupCommand(const char *ChatCommand) {
|
|||||||
|
|
||||||
for (int i = 0; i < CommandEndOfList; i++) {
|
for (int i = 0; i < CommandEndOfList; i++) {
|
||||||
|
|
||||||
if (!strcasecmp(Commands[i].CommandString, ChatCommand))
|
if (!strcasecmp(Commands[i].CommandString, ChatCommand)) {
|
||||||
return Commands[i].CommandCode;
|
return Commands[i].CommandCode;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -594,6 +596,28 @@ void Clientlist::CheckForStaleConnections(Client *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string RemoveDuplicateChannels(const std::string& in_channels) {
|
||||||
|
// Split the string by ", " and store the names in a vector
|
||||||
|
std::vector<std::string> channel_names = Strings::Split(in_channels, ", ");
|
||||||
|
|
||||||
|
// Remove duplicates by inserting the names of the channels into an unordered set
|
||||||
|
// and then copying the unique elements back into the original vector
|
||||||
|
std::unordered_set<std::string> unique_channels;
|
||||||
|
channel_names.erase(
|
||||||
|
std::remove_if(
|
||||||
|
channel_names.begin(), channel_names.end(),
|
||||||
|
[&unique_channels](const std::string &channel) {
|
||||||
|
return !unique_channels.insert(channel).second;
|
||||||
|
}
|
||||||
|
), channel_names.end()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Concatenate the names of the unique channels into a single string
|
||||||
|
std::string unique_channels_string = Strings::Implode(", ", channel_names);
|
||||||
|
|
||||||
|
return unique_channels_string;
|
||||||
|
}
|
||||||
|
|
||||||
void Clientlist::Process()
|
void Clientlist::Process()
|
||||||
{
|
{
|
||||||
auto it = ClientChatConnections.begin();
|
auto it = ClientChatConnections.begin();
|
||||||
@ -682,10 +706,18 @@ void Clientlist::Process()
|
|||||||
CheckForStaleConnections((*it));
|
CheckForStaleConnections((*it));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_Mail: {
|
case OP_Mail: {
|
||||||
std::string CommandString = (const char *)app->pBuffer + 1;
|
std::string command_string = (const char *)app->pBuffer + 1;
|
||||||
ProcessOPMailCommand((*it), CommandString);
|
bool command_directed = false;
|
||||||
|
if (command_string.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Strings::Contains(Strings::ToLower(command_string), "leave")) {
|
||||||
|
command_directed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessOPMailCommand((*it), command_string, command_directed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,106 +748,112 @@ void Clientlist::Process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
|
void Clientlist::ProcessOPMailCommand(Client *c, std::string command_string, bool command_directed)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (CommandString.length() == 0)
|
if (command_string.length() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isdigit(CommandString[0]))
|
if (isdigit(command_string[0]))
|
||||||
{
|
{
|
||||||
|
|
||||||
c->SendChannelMessageByNumber(CommandString);
|
c->SendChannelMessageByNumber(command_string);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CommandString[0] == '#') {
|
if (command_string[0] == '#') {
|
||||||
|
|
||||||
c->SendChannelMessage(CommandString);
|
c->SendChannelMessage(command_string);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Command, Parameters;
|
std::string command, parameters;
|
||||||
|
|
||||||
std::string::size_type Space = CommandString.find_first_of(" ");
|
std::string::size_type Space = command_string.find_first_of(" ");
|
||||||
|
|
||||||
if (Space != std::string::npos) {
|
if (Space != std::string::npos) {
|
||||||
|
|
||||||
Command = CommandString.substr(0, Space);
|
command = command_string.substr(0, Space);
|
||||||
|
|
||||||
std::string::size_type ParametersStart = CommandString.find_first_not_of(" ", Space);
|
std::string::size_type parameters_start = command_string.find_first_not_of(" ", Space);
|
||||||
|
|
||||||
if (ParametersStart != std::string::npos)
|
if (parameters_start != std::string::npos)
|
||||||
Parameters = CommandString.substr(ParametersStart);
|
parameters = command_string.substr(parameters_start);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
command = command_string;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Command = CommandString;
|
|
||||||
|
|
||||||
int CommandCode = LookupCommand(Command.c_str());
|
auto command_code = LookupCommand(command.c_str());
|
||||||
|
switch (command_code) {
|
||||||
switch (CommandCode) {
|
|
||||||
|
|
||||||
case CommandJoin:
|
case CommandJoin:
|
||||||
c->JoinChannels(Parameters);
|
if (!command_directed) {
|
||||||
|
//Append saved channels to params
|
||||||
|
parameters = parameters + ", " + database.CurrentPlayerChannels(c->GetName());
|
||||||
|
parameters = RemoveDuplicateChannels(parameters);
|
||||||
|
}
|
||||||
|
c->JoinChannels(parameters, command_directed);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandLeaveAll:
|
case CommandLeaveAll:
|
||||||
c->LeaveAllChannels();
|
c->LeaveAllChannels(true, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandLeave:
|
case CommandLeave:
|
||||||
c->LeaveChannels(Parameters);
|
c->LeaveChannels(parameters, command_directed);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandListAll:
|
case CommandListAll:
|
||||||
|
|
||||||
ChannelList->SendAllChannels(c);
|
ChannelList->SendAllChannels(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandList:
|
case CommandList:
|
||||||
c->ProcessChannelList(Parameters);
|
c->ProcessChannelList(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandSet:
|
case CommandSet:
|
||||||
c->LeaveAllChannels(false);
|
c->LeaveAllChannels(false);
|
||||||
c->JoinChannels(Parameters);
|
c->JoinChannels(parameters, command_directed);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandAnnounce:
|
case CommandAnnounce:
|
||||||
c->ToggleAnnounce(Parameters);
|
c->ToggleAnnounce(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandSetOwner:
|
case CommandSetOwner:
|
||||||
c->SetChannelOwner(Parameters);
|
c->SetChannelOwner(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandOPList:
|
case CommandOPList:
|
||||||
c->OPList(Parameters);
|
c->OPList(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandInvite:
|
case CommandInvite:
|
||||||
c->ChannelInvite(Parameters);
|
c->ChannelInvite(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandGrant:
|
case CommandGrant:
|
||||||
c->ChannelGrantModerator(Parameters);
|
c->ChannelGrantModerator(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandModerate:
|
case CommandModerate:
|
||||||
c->ChannelModerate(Parameters);
|
c->ChannelModerate(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandVoice:
|
case CommandVoice:
|
||||||
c->ChannelGrantVoice(Parameters);
|
c->ChannelGrantVoice(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandKick:
|
case CommandKick:
|
||||||
c->ChannelKick(Parameters);
|
c->ChannelKick(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandPassword:
|
case CommandPassword:
|
||||||
c->SetChannelPassword(Parameters);
|
c->SetChannelPassword(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandToggleInvites:
|
case CommandToggleInvites:
|
||||||
@ -834,43 +872,44 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandGetBody:
|
case CommandGetBody:
|
||||||
database.SendBody(c, atoi(Parameters.c_str()));
|
database.SendBody(c, atoi(parameters.c_str()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandMailTo:
|
case CommandMailTo:
|
||||||
ProcessMailTo(c, Parameters);
|
ProcessMailTo(c, parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandSetMessageStatus:
|
case CommandSetMessageStatus:
|
||||||
LogInfo("Set Message Status, Params: [{}]", Parameters.c_str());
|
LogInfo("Set Message Status, Params: [{}]", parameters.c_str());
|
||||||
ProcessSetMessageStatus(Parameters);
|
ProcessSetMessageStatus(parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandSelectMailBox:
|
case CommandSelectMailBox:
|
||||||
{
|
{
|
||||||
std::string::size_type NumStart = Parameters.find_first_of("0123456789");
|
std::string::size_type NumStart = parameters.find_first_of("0123456789");
|
||||||
c->ChangeMailBox(atoi(Parameters.substr(NumStart).c_str()));
|
c->ChangeMailBox(atoi(parameters.substr(NumStart).c_str()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CommandSetMailForwarding:
|
case CommandSetMailForwarding:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandBuddy:
|
case CommandBuddy:
|
||||||
RemoveApostrophes(Parameters);
|
RemoveApostrophes(parameters);
|
||||||
ProcessCommandBuddy(c, Parameters);
|
ProcessCommandBuddy(c, parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CommandIgnorePlayer:
|
case CommandIgnorePlayer:
|
||||||
RemoveApostrophes(Parameters);
|
RemoveApostrophes(parameters);
|
||||||
ProcessCommandIgnore(c, Parameters);
|
ProcessCommandIgnore(c, parameters);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
c->SendHelp();
|
c->SendHelp();
|
||||||
LogInfo("Unhandled OP_Mail command: [{}]", CommandString.c_str());
|
LogInfo("Unhandled OP_Mail command: [{}]", command_string.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Clientlist::CloseAllConnections() {
|
void Clientlist::CloseAllConnections() {
|
||||||
|
|
||||||
|
|
||||||
@ -992,51 +1031,51 @@ int Client::ChannelCount() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::JoinChannels(std::string ChannelNameList) {
|
void Client::JoinChannels(std::string& channel_name_list, bool command_directed) {
|
||||||
|
|
||||||
for (auto &elem : ChannelNameList) {
|
for (auto &elem : channel_name_list) {
|
||||||
if (elem == '%') {
|
if (elem == '%') {
|
||||||
elem = '/';
|
elem = '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Client: [{}] joining channels [{}]", GetName().c_str(), ChannelNameList.c_str());
|
LogInfo("Client: [{}] joining channels [{}]", GetName().c_str(), channel_name_list.c_str());
|
||||||
|
|
||||||
int NumberOfChannels = ChannelCount();
|
auto number_of_channels = ChannelCount();
|
||||||
|
|
||||||
std::string::size_type CurrentPos = ChannelNameList.find_first_not_of(" ");
|
auto current_pos = channel_name_list.find_first_not_of(" ");
|
||||||
|
|
||||||
while (CurrentPos != std::string::npos) {
|
while (current_pos != std::string::npos) {
|
||||||
|
|
||||||
if (NumberOfChannels == MAX_JOINED_CHANNELS) {
|
if (number_of_channels == MAX_JOINED_CHANNELS) {
|
||||||
|
|
||||||
GeneralChannelMessage("You have joined the maximum number of channels. /leave one before trying to join another.");
|
GeneralChannelMessage("You have joined the maximum number of channels. /leave one before trying to join another.");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string::size_type Comma = ChannelNameList.find_first_of(", ", CurrentPos);
|
auto comma = channel_name_list.find_first_of(", ", current_pos);
|
||||||
|
|
||||||
if (Comma == std::string::npos) {
|
if (comma == std::string::npos) {
|
||||||
|
auto* joined_channel = ChannelList->AddClientToChannel(channel_name_list.substr(current_pos), this, command_directed);
|
||||||
|
|
||||||
ChatChannel* JoinedChannel = ChannelList->AddClientToChannel(ChannelNameList.substr(CurrentPos), this);
|
if (joined_channel) {
|
||||||
|
AddToChannelList(joined_channel);
|
||||||
if (JoinedChannel)
|
}
|
||||||
AddToChannelList(JoinedChannel);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatChannel* JoinedChannel = ChannelList->AddClientToChannel(ChannelNameList.substr(CurrentPos, Comma - CurrentPos), this);
|
auto* joined_channel = ChannelList->AddClientToChannel(channel_name_list.substr(current_pos, comma - current_pos), this, command_directed);
|
||||||
|
|
||||||
if (JoinedChannel) {
|
if (joined_channel) {
|
||||||
|
|
||||||
AddToChannelList(JoinedChannel);
|
AddToChannelList(joined_channel);
|
||||||
|
|
||||||
NumberOfChannels++;
|
number_of_channels++;
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentPos = ChannelNameList.find_first_not_of(", ", Comma);
|
current_pos = channel_name_list.find_first_not_of(", ", comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string JoinedChannelsList, ChannelMessage;
|
std::string JoinedChannelsList, ChannelMessage;
|
||||||
@ -1097,37 +1136,36 @@ void Client::JoinChannels(std::string ChannelNameList) {
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::LeaveChannels(std::string ChannelNameList) {
|
void Client::LeaveChannels(std::string& channel_name_list, bool command_directed) {
|
||||||
|
LogInfo("Client: [{}] leaving channels [{}]", GetName().c_str(), channel_name_list.c_str());
|
||||||
|
|
||||||
LogInfo("Client: [{}] leaving channels [{}]", GetName().c_str(), ChannelNameList.c_str());
|
auto current_pos = 0;
|
||||||
|
|
||||||
std::string::size_type CurrentPos = 0;
|
while (current_pos != std::string::npos) {
|
||||||
|
|
||||||
while (CurrentPos != std::string::npos) {
|
std::string::size_type Comma = channel_name_list.find_first_of(", ", current_pos);
|
||||||
|
|
||||||
std::string::size_type Comma = ChannelNameList.find_first_of(", ", CurrentPos);
|
|
||||||
|
|
||||||
if (Comma == std::string::npos) {
|
if (Comma == std::string::npos) {
|
||||||
|
|
||||||
ChatChannel* JoinedChannel = ChannelList->RemoveClientFromChannel(ChannelNameList.substr(CurrentPos), this);
|
auto* joined_channel = ChannelList->RemoveClientFromChannel(channel_name_list.substr(current_pos), this, command_directed);
|
||||||
|
|
||||||
if (JoinedChannel)
|
if (joined_channel)
|
||||||
RemoveFromChannelList(JoinedChannel);
|
RemoveFromChannelList(joined_channel);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatChannel* JoinedChannel = ChannelList->RemoveClientFromChannel(ChannelNameList.substr(CurrentPos, Comma - CurrentPos), this);
|
auto* joined_channel = ChannelList->RemoveClientFromChannel(channel_name_list.substr(current_pos, Comma - current_pos), this, command_directed);
|
||||||
|
|
||||||
if (JoinedChannel)
|
if (joined_channel)
|
||||||
RemoveFromChannelList(JoinedChannel);
|
RemoveFromChannelList(joined_channel);
|
||||||
|
|
||||||
CurrentPos = ChannelNameList.find_first_not_of(", ", Comma);
|
current_pos = channel_name_list.find_first_not_of(", ", Comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string JoinedChannelsList, ChannelMessage;
|
std::string joined_channels_list, channel_message;
|
||||||
|
|
||||||
ChannelMessage = "Channels: ";
|
channel_message = "Channels: ";
|
||||||
|
|
||||||
char tmp[200];
|
char tmp[200];
|
||||||
|
|
||||||
@ -1139,26 +1177,26 @@ void Client::LeaveChannels(std::string ChannelNameList) {
|
|||||||
|
|
||||||
if (ChannelCount) {
|
if (ChannelCount) {
|
||||||
|
|
||||||
JoinedChannelsList = JoinedChannelsList + ",";
|
joined_channels_list = joined_channels_list + ",";
|
||||||
|
|
||||||
ChannelMessage = ChannelMessage + ",";
|
channel_message = channel_message + ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
JoinedChannelsList = JoinedChannelsList + JoinedChannels[i]->GetName();
|
joined_channels_list = joined_channels_list + JoinedChannels[i]->GetName();
|
||||||
|
|
||||||
sprintf(tmp, "%i=%s(%i)", i + 1, JoinedChannels[i]->GetName().c_str(), JoinedChannels[i]->MemberCount(Status));
|
sprintf(tmp, "%i=%s(%i)", i + 1, JoinedChannels[i]->GetName().c_str(), JoinedChannels[i]->MemberCount(Status));
|
||||||
|
|
||||||
ChannelMessage += tmp;
|
channel_message += tmp;
|
||||||
|
|
||||||
ChannelCount++;
|
ChannelCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_Mail, JoinedChannelsList.length() + 1);
|
auto outapp = new EQApplicationPacket(OP_Mail, joined_channels_list.length() + 1);
|
||||||
|
|
||||||
char *PacketBuffer = (char *)outapp->pBuffer;
|
char *PacketBuffer = (char *)outapp->pBuffer;
|
||||||
|
|
||||||
sprintf(PacketBuffer, "%s", JoinedChannelsList.c_str());
|
sprintf(PacketBuffer, "%s", joined_channels_list.c_str());
|
||||||
|
|
||||||
|
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
@ -1166,15 +1204,15 @@ void Client::LeaveChannels(std::string ChannelNameList) {
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
if (ChannelCount == 0)
|
if (ChannelCount == 0)
|
||||||
ChannelMessage = "You are not on any channels.";
|
channel_message = "You are not on any channels.";
|
||||||
|
|
||||||
outapp = new EQApplicationPacket(OP_ChannelMessage, ChannelMessage.length() + 3);
|
outapp = new EQApplicationPacket(OP_ChannelMessage, channel_message.length() + 3);
|
||||||
|
|
||||||
PacketBuffer = (char *)outapp->pBuffer;
|
PacketBuffer = (char *)outapp->pBuffer;
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x00);
|
VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x00);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x00);
|
VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x00);
|
||||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, ChannelMessage.c_str());
|
VARSTRUCT_ENCODE_STRING(PacketBuffer, channel_message.c_str());
|
||||||
|
|
||||||
|
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
@ -1182,19 +1220,19 @@ void Client::LeaveChannels(std::string ChannelNameList) {
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::LeaveAllChannels(bool SendUpdatedChannelList) {
|
void Client::LeaveAllChannels(bool send_updated_channel_list, bool command_directed) {
|
||||||
|
|
||||||
for (auto &elem : JoinedChannels) {
|
for (auto &elem : JoinedChannels) {
|
||||||
|
|
||||||
if (elem) {
|
if (elem) {
|
||||||
|
|
||||||
ChannelList->RemoveClientFromChannel(elem->GetName(), this);
|
ChannelList->RemoveClientFromChannel(elem->GetName(), this, command_directed);
|
||||||
|
|
||||||
elem = nullptr;
|
elem = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SendUpdatedChannelList)
|
if (send_updated_channel_list)
|
||||||
SendChannelList();
|
SendChannelList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1643,6 +1681,7 @@ void Client::SetChannelPassword(std::string ChannelPassword) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RequiredChannel->SetPassword(Password);
|
RequiredChannel->SetPassword(Password);
|
||||||
|
database.SaveChatChannel(RequiredChannel->GetName(), RequiredChannel->GetOwnerName(), Password, RequiredChannel->GetMinStatus()); // Update DB with new password
|
||||||
|
|
||||||
GeneralChannelMessage(Message);
|
GeneralChannelMessage(Message);
|
||||||
|
|
||||||
@ -1703,6 +1742,7 @@ void Client::SetChannelOwner(std::string CommandString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RequiredChannel->SetOwner(NewOwner);
|
RequiredChannel->SetOwner(NewOwner);
|
||||||
|
database.SaveChatChannel(RequiredChannel->GetName(), NewOwner, RequiredChannel->GetPassword(), RequiredChannel->GetMinStatus()); // Update DB with new owner
|
||||||
|
|
||||||
if (RequiredChannel->IsModerator(NewOwner))
|
if (RequiredChannel->IsModerator(NewOwner))
|
||||||
RequiredChannel->RemoveModerator(NewOwner);
|
RequiredChannel->RemoveModerator(NewOwner);
|
||||||
@ -2121,7 +2161,7 @@ void Client::ChannelKick(std::string CommandString) {
|
|||||||
|
|
||||||
GeneralChannelMessage("Kicked " + Kickee + " from channel " + ChannelName);
|
GeneralChannelMessage("Kicked " + Kickee + " from channel " + ChannelName);
|
||||||
|
|
||||||
RequiredClient->LeaveChannels(ChannelName);
|
RequiredClient->LeaveChannels(ChannelName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ToggleInvites() {
|
void Client::ToggleInvites() {
|
||||||
|
|||||||
@ -92,9 +92,9 @@ public:
|
|||||||
void SendMailBoxes();
|
void SendMailBoxes();
|
||||||
inline void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) { ClientStream->QueuePacket(p, ack_req); }
|
inline void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) { ClientStream->QueuePacket(p, ack_req); }
|
||||||
std::string GetName() { if(Characters.size()) return Characters[0].Name; else return ""; }
|
std::string GetName() { if(Characters.size()) return Characters[0].Name; else return ""; }
|
||||||
void JoinChannels(std::string ChannelList);
|
void JoinChannels(std::string& channel_name_list, bool command_directed = false);
|
||||||
void LeaveChannels(std::string ChannelList);
|
void LeaveChannels(std::string& channel_name_list, bool command_directed = false);
|
||||||
void LeaveAllChannels(bool SendUpdatedChannelList = true);
|
void LeaveAllChannels(bool send_updated_channel_list = true, bool command_directed = false);
|
||||||
void AddToChannelList(ChatChannel *JoinedChannel);
|
void AddToChannelList(ChatChannel *JoinedChannel);
|
||||||
void RemoveFromChannelList(ChatChannel *JoinedChannel);
|
void RemoveFromChannelList(ChatChannel *JoinedChannel);
|
||||||
void SendChannelMessage(std::string Message);
|
void SendChannelMessage(std::string Message);
|
||||||
@ -112,6 +112,7 @@ public:
|
|||||||
void ProcessChannelList(std::string CommandString);
|
void ProcessChannelList(std::string CommandString);
|
||||||
void AccountUpdate();
|
void AccountUpdate();
|
||||||
int ChannelCount();
|
int ChannelCount();
|
||||||
|
std::string RemoveDuplicateChannels(std::string& in_channels);
|
||||||
inline void SetAccountID(int inAccountID) { AccountID = inAccountID; }
|
inline void SetAccountID(int inAccountID) { AccountID = inAccountID; }
|
||||||
inline int GetAccountID() { return AccountID; }
|
inline int GetAccountID() { return AccountID; }
|
||||||
inline void SetAccountStatus(int inStatus) { Status = inStatus; }
|
inline void SetAccountStatus(int inStatus) { Status = inStatus; }
|
||||||
@ -187,7 +188,7 @@ public:
|
|||||||
void CheckForStaleConnectionsAll();
|
void CheckForStaleConnectionsAll();
|
||||||
void CheckForStaleConnections(Client *c);
|
void CheckForStaleConnections(Client *c);
|
||||||
Client *IsCharacterOnline(std::string CharacterName);
|
Client *IsCharacterOnline(std::string CharacterName);
|
||||||
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
void ProcessOPMailCommand(Client* c, std::string command_string, bool command_directed = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EQ::Net::EQStreamManager *chatsf;
|
EQ::Net::EQStreamManager *chatsf;
|
||||||
|
|||||||
168
ucs/database.cpp
168
ucs/database.cpp
@ -49,6 +49,9 @@
|
|||||||
#include "../common/misc_functions.h"
|
#include "../common/misc_functions.h"
|
||||||
#include "../common/strings.h"
|
#include "../common/strings.h"
|
||||||
#include "chatchannel.h"
|
#include "chatchannel.h"
|
||||||
|
#include "../common/repositories/chatchannel_reserved_names_repository.h"
|
||||||
|
#include "../common/repositories/chatchannels_repository.h"
|
||||||
|
#include "../common/repositories/name_filter_repository.h"
|
||||||
|
|
||||||
extern Clientlist *g_Clientlist;
|
extern Clientlist *g_Clientlist;
|
||||||
extern std::string GetMailPrefix();
|
extern std::string GetMailPrefix();
|
||||||
@ -219,51 +222,160 @@ bool UCSDatabase::GetVariable(const char *varname, char *varvalue, uint16 varval
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool UCSDatabase::LoadChatChannels()
|
bool UCSDatabase::LoadChatChannels()
|
||||||
{
|
{
|
||||||
|
LoadReservedNamesFromDB();
|
||||||
LogInfo("Loading chat channels from the database");
|
LogInfo("Loading chat channels from the database");
|
||||||
|
|
||||||
const std::string query = "SELECT `name`, `owner`, `password`, `minstatus` FROM `chatchannels`";
|
const std::string query = "SELECT `name`, `owner`, `password`, `minstatus` FROM `chatchannels`";
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
std::string channelName = row[0];
|
std::string channel_name = row[0];
|
||||||
std::string channelOwner = row[1];
|
std::string channel_owner = row[1];
|
||||||
std::string channelPassword = row[2];
|
std::string channel_password = row[2];
|
||||||
|
auto channel_min_status = row[3];
|
||||||
|
|
||||||
ChannelList->CreateChannel(channelName, channelOwner, channelPassword, true, atoi(row[3]));
|
if (!ChannelList->FindChannel(channel_name)) {
|
||||||
|
ChannelList->CreateChannel(channel_name, channel_owner, channel_password, true, atoi(channel_min_status), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSDatabase::SetChannelPassword(std::string channelName, std::string password)
|
void UCSDatabase::LoadReservedNamesFromDB()
|
||||||
{
|
{
|
||||||
LogInfo("UCSDatabase::SetChannelPassword([{}], [{}])", channelName.c_str(), password.c_str());
|
ChatChannelList::ClearChannelBlockList();
|
||||||
|
|
||||||
std::string query = StringFormat(
|
auto channels = ChatchannelReservedNamesRepository::All(*this);
|
||||||
"UPDATE `chatchannels` SET `password` = '%s' WHERE `name` = '%s'",
|
if (channels.empty()) {
|
||||||
password.c_str(), channelName.c_str());
|
LogDebug("No reserved names exist in the database...");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &e: channels) {
|
||||||
|
ChatChannelList::AddToChannelBlockList(e.name);
|
||||||
|
LogInfo("Adding channel [{}] to blocked list from database...", e.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("Loaded [{}] reserved channel name(s)", channels.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UCSDatabase::IsChatChannelInDB(const std::string& channel_name)
|
||||||
|
{
|
||||||
|
auto r = ChatchannelsRepository::Count(
|
||||||
|
*this,
|
||||||
|
fmt::format(
|
||||||
|
"name = {}", Strings::Escape(channel_name)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return r > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCSDatabase::SaveChatChannel(
|
||||||
|
const std::string& channel_name,
|
||||||
|
const std::string& channel_owner,
|
||||||
|
const std::string& channel_password,
|
||||||
|
const uint16& min_status
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto e = ChatchannelsRepository::GetWhere(
|
||||||
|
*this,
|
||||||
|
fmt::format(
|
||||||
|
"`name` = '{}' LIMIT 1", Strings::Escape(channel_name)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// If channel name is blocked, do not save it to the database
|
||||||
|
if (ChatChannelList::IsOnChannelBlockList(channel_name)) {
|
||||||
|
LogInfo("Channel [{}] already found on the block list, ignoring", channel_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update if exists, create new if it doesn't
|
||||||
|
auto c = !e.empty() ? e[0] : ChatchannelsRepository::NewEntity();
|
||||||
|
c.name = channel_name;
|
||||||
|
c.owner = channel_owner;
|
||||||
|
c.password = channel_password;
|
||||||
|
c.minstatus = min_status;
|
||||||
|
|
||||||
|
if (e.empty()) {
|
||||||
|
ChatchannelsRepository::InsertOne(*this, c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatchannelsRepository::UpdateOne(*this, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCSDatabase::DeleteChatChannel(const std::string& channel_name)
|
||||||
|
{
|
||||||
|
ChatchannelsRepository::DeleteWhere(*this, fmt::format("`name` = '{}'", Strings::Escape(channel_name)));
|
||||||
|
LogInfo("Deleting channel [{}] from the database.", channel_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string UCSDatabase::CurrentPlayerChannels(const std::string& player_name) {
|
||||||
|
int current_player_channel_count = CurrentPlayerChannelCount(player_name);
|
||||||
|
if (current_player_channel_count == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const auto rquery = fmt::format("SELECT GROUP_CONCAT(`name` SEPARATOR ', ') FROM chatchannels WHERE `owner` = '{}'; ", Strings::Escape(player_name));
|
||||||
|
auto results = QueryDatabase(rquery);
|
||||||
|
auto row = results.begin();
|
||||||
|
std::string channels = row[0];
|
||||||
|
LogDebug("Player [{}] has the following permanent channels saved to the database: [{}].", player_name, channels);
|
||||||
|
return channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UCSDatabase::CurrentPlayerChannelCount(const std::string& player_name)
|
||||||
|
{
|
||||||
|
return (int) ChatchannelsRepository::Count(*this, fmt::format("`owner` = '{}'", Strings::Escape(player_name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCSDatabase::SetChannelPassword(const std::string& channel_name, const std::string& password)
|
||||||
|
{
|
||||||
|
LogInfo("UCSDatabase::SetChannelPassword([{}], [{}])", channel_name.c_str(), password.c_str());
|
||||||
|
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"UPDATE `chatchannels` SET `password` = '{}' WHERE `name` = '{}'",
|
||||||
|
Strings::Escape(password), Strings::Escape(channel_name));
|
||||||
QueryDatabase(query);
|
QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSDatabase::SetChannelOwner(std::string channelName, std::string owner)
|
void UCSDatabase::SetChannelOwner(const std::string& channel_name, const std::string& owner)
|
||||||
{
|
{
|
||||||
LogInfo("UCSDatabase::SetChannelOwner([{}], [{}])", channelName.c_str(), owner.c_str());
|
LogInfo("Setting channel [{}] owner to [{}]", channel_name, owner);
|
||||||
|
|
||||||
std::string query = StringFormat(
|
std::string query = fmt::format(
|
||||||
"UPDATE `chatchannels` SET `owner` = '%s' WHERE `name` = '%s'",
|
"UPDATE `chatchannels` SET `owner` = '{}' WHERE `name` = '{}'",
|
||||||
owner.c_str(),
|
Strings::Escape(owner),
|
||||||
channelName.c_str()
|
Strings::Escape(channel_name)
|
||||||
);
|
);
|
||||||
|
|
||||||
QueryDatabase(query);
|
QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UCSDatabase::CheckChannelNameFilter(const std::string& channel_name)
|
||||||
|
{
|
||||||
|
LogDebug("Checking if [{}] is on the name filter", channel_name);
|
||||||
|
|
||||||
|
// TODO: This should potentially just be pulled into memory at some other point
|
||||||
|
// This if fine for now
|
||||||
|
for (auto &e: NameFilterRepository::All(*this)) {
|
||||||
|
if (Strings::Contains(Strings::ToLower(channel_name), Strings::ToLower(e.name))) {
|
||||||
|
LogInfo("Failed to pass name filter check for [{}] against word [{}]", channel_name, e.name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogDebug("Name Filter Check Passed!");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void UCSDatabase::SendHeaders(Client *client)
|
void UCSDatabase::SendHeaders(Client *client)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -356,7 +468,7 @@ void UCSDatabase::SendHeaders(Client *client)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSDatabase::SendBody(Client *client, int messageNumber)
|
void UCSDatabase::SendBody(Client *client, const int& messageNumber)
|
||||||
{
|
{
|
||||||
|
|
||||||
int characterID = FindCharacter(client->MailBoxName().c_str());
|
int characterID = FindCharacter(client->MailBoxName().c_str());
|
||||||
@ -412,11 +524,11 @@ void UCSDatabase::SendBody(Client *client, int messageNumber)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool UCSDatabase::SendMail(
|
bool UCSDatabase::SendMail(
|
||||||
std::string recipient,
|
const std::string& recipient,
|
||||||
std::string from,
|
const std::string& from,
|
||||||
std::string subject,
|
const std::string& subject,
|
||||||
std::string body,
|
const std::string& body,
|
||||||
std::string recipientsString
|
const std::string& recipientsString
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -484,7 +596,7 @@ bool UCSDatabase::SendMail(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSDatabase::SetMessageStatus(int messageNumber, int status)
|
void UCSDatabase::SetMessageStatus(const int& messageNumber, const int& status)
|
||||||
{
|
{
|
||||||
|
|
||||||
LogInfo("SetMessageStatus [{}] [{}]", messageNumber, status);
|
LogInfo("SetMessageStatus [{}] [{}]", messageNumber, status);
|
||||||
@ -557,7 +669,7 @@ void UCSDatabase::ExpireMail()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSDatabase::AddFriendOrIgnore(int charID, int type, std::string name)
|
void UCSDatabase::AddFriendOrIgnore(const int& charID, const int& type, const std::string& name)
|
||||||
{
|
{
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"INSERT INTO `friends` (`charid`, `type`, `name`) "
|
"INSERT INTO `friends` (`charid`, `type`, `name`) "
|
||||||
@ -579,7 +691,7 @@ void UCSDatabase::AddFriendOrIgnore(int charID, int type, std::string name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSDatabase::RemoveFriendOrIgnore(int charID, int type, std::string name)
|
void UCSDatabase::RemoveFriendOrIgnore(const int& charID, const int& type, const std::string& name)
|
||||||
{
|
{
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"DELETE FROM `friends` WHERE `charid` = %i AND `type` = %i AND `name` = '%s'",
|
"DELETE FROM `friends` WHERE `charid` = %i AND `type` = %i AND `name` = '%s'",
|
||||||
@ -600,7 +712,7 @@ void UCSDatabase::RemoveFriendOrIgnore(int charID, int type, std::string name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UCSDatabase::GetFriendsAndIgnore(int charID, std::vector<std::string> &friends, std::vector<std::string> &ignorees)
|
void UCSDatabase::GetFriendsAndIgnore(const int& charID, std::vector<std::string> &friends, std::vector<std::string> &ignorees)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string query = StringFormat("select `type`, `name` FROM `friends` WHERE `charid`=%i", charID);
|
std::string query = StringFormat("select `type`, `name` FROM `friends` WHERE `charid`=%i", charID);
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
are required to give you total support for your newly bought product;
|
are required to give you total support for your newly bought product
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
@ -27,7 +27,9 @@
|
|||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
#include "../common/database.h"
|
#include "../common/database.h"
|
||||||
#include "../common/linked_list.h"
|
#include "../common/linked_list.h"
|
||||||
|
#include "../common/database.h"
|
||||||
#include "clientlist.h"
|
#include "clientlist.h"
|
||||||
|
#include "chatchannel.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -42,18 +44,24 @@ public:
|
|||||||
bool VerifyMailKey(std::string CharacterName, int IPAddress, std::string MailKey);
|
bool VerifyMailKey(std::string CharacterName, int IPAddress, std::string MailKey);
|
||||||
bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len);
|
bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len);
|
||||||
bool LoadChatChannels();
|
bool LoadChatChannels();
|
||||||
|
void LoadReservedNamesFromDB();
|
||||||
|
bool IsChatChannelInDB(const std::string& channel_name);
|
||||||
|
bool CheckChannelNameFilter(const std::string& channel_name);
|
||||||
|
void SaveChatChannel(const std::string& channel_name, const std::string& channel_owner, const std::string& channel_password, const uint16& min_status);
|
||||||
|
void DeleteChatChannel(const std::string& channel_name);
|
||||||
|
int CurrentPlayerChannelCount(const std::string& player_name);
|
||||||
|
std::string CurrentPlayerChannels(const std::string& player_name);
|
||||||
void GetAccountStatus(Client *c);
|
void GetAccountStatus(Client *c);
|
||||||
void SetChannelPassword(std::string ChannelName, std::string Password);
|
void SetChannelPassword(const std::string& channel_name, const std::string& password);
|
||||||
void SetChannelOwner(std::string ChannelName, std::string Owner);
|
void SetChannelOwner(const std::string& channel_name, const std::string& owner);
|
||||||
void SendHeaders(Client *c);
|
void SendHeaders(Client *c);
|
||||||
void SendBody(Client *c, int MessageNumber);
|
void SendBody(Client *c, const int& message_number);
|
||||||
bool SendMail(std::string Recipient, std::string From, std::string Subject, std::string Body, std::string RecipientsString);
|
bool SendMail(const std::string& recipient, const std::string& from, const std::string& subject, const std::string& body, const std::string& recipients_string);
|
||||||
void SetMessageStatus(int MessageNumber, int Status);
|
void SetMessageStatus(const int& message_number, const int& Status);
|
||||||
void ExpireMail();
|
void ExpireMail();
|
||||||
void AddFriendOrIgnore(int CharID, int Type, std::string Name);
|
void AddFriendOrIgnore(const int& char_id, const int& type, const std::string& name);
|
||||||
void RemoveFriendOrIgnore(int CharID, int Type, std::string Name);
|
void RemoveFriendOrIgnore(const int& char_id, const int& type, const std::string& name);
|
||||||
void GetFriendsAndIgnore(int CharID, std::vector<std::string> &Friends, std::vector<std::string> &Ignorees);
|
void GetFriendsAndIgnore(const int& char_id, std::vector<std::string> &Friends, std::vector<std::string> &Ignorees);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void HandleMysqlError(uint32 errnum);
|
void HandleMysqlError(uint32 errnum);
|
||||||
|
|||||||
@ -138,7 +138,7 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
|
|||||||
}
|
}
|
||||||
else if (Message[0] == '[')
|
else if (Message[0] == '[')
|
||||||
{
|
{
|
||||||
g_Clientlist->ProcessOPMailCommand(c, Message.substr(1, std::string::npos));
|
g_Clientlist->ProcessOPMailCommand(c, Message.substr(1, std::string::npos), true); // Flag as command_directed
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -470,6 +470,7 @@
|
|||||||
9214|2022_12_24_character_exp_toggle.sql|SHOW COLUMNS FROM `character_data` LIKE 'exp_enabled'|empty|
|
9214|2022_12_24_character_exp_toggle.sql|SHOW COLUMNS FROM `character_data` LIKE 'exp_enabled'|empty|
|
||||||
9215|2023_01_08_zone_max_level.sql|SHOW COLUMNS FROM `zone` LIKE 'max_level'|empty|
|
9215|2023_01_08_zone_max_level.sql|SHOW COLUMNS FROM `zone` LIKE 'max_level'|empty|
|
||||||
9216|2023_01_15_merc_data.sql|SHOW TABLES LIKE 'mercs'|empty|
|
9216|2023_01_15_merc_data.sql|SHOW TABLES LIKE 'mercs'|empty|
|
||||||
|
9217|2023_01_15_chatchannel_reserved_names.sql|SHOW TABLES LIKE 'chatchannel_reserved_names'|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
CREATE TABLE `chatchannel_reserved_names`
|
||||||
|
(
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(64) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE KEY `name` (`name`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
ALTER TABLE `chatchannels`
|
||||||
|
ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
ADD PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
ADD UNIQUE INDEX(`name`)
|
||||||
Loading…
x
Reference in New Issue
Block a user