A discord bot that can send messages from a discord channel to a channel in rAthena and back! Keep your in-game players in contact with your offline community!
This is similar to roCORD, but technically this was first :D. This also performs much better than other implementations.
Add the Trog Server Bot from the member list on the Troglodytes discord, then use /setup
in your discord server!
In order to not overload your server with spam, I recommend turning on slowmode on your discord channels.
@requests sent from a character creates a new discord channel in this category. Any message in this discord channel gets sent back to the character. This is great to help players while the GMs aren't online, as they can respond from discord.
Price is based on feature set.
This requires only a couple of changes, much easier than the trog proxy service.
UPDATED November 1st, 2023.
You can find the diff here: https://gist.github.com/vstumpf/8fa4ab356be882e538f1794c2e39fb34
Alternatively, follow the steps below:
1) Create the following files
1a) conf/discord_athena.conf
https://gist.github.com/vstumpf/e7645581ed0370db13403436c5ce2f53#file-discord_athena-conf
1b) conf/import-tmpl/discord_conf.txt
https://gist.github.com/vstumpf/e7645581ed0370db13403436c5ce2f53#file-discord_conf-txt
1c) src/map/disif.cpp
https://gist.github.com/vstumpf/e7645581ed0370db13403436c5ce2f53#file-disif-cpp
1d) src/map/disif.hpp
https://gist.github.com/vstumpf/e7645581ed0370db13403436c5ce2f53#file-disif-hpp
2) In socket.cpp
2a) change
int make_connection(uint32 ip, uint16 port, bool silent,int timeout) {
to
int make_connection(uint32 ip, uint16 port, bool silent,int timeout, bool nonblocking) {
2b) change
#else
result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
if( result == SOCKET_ERROR ) {
if( !silent )
to
#else
if (nonblocking)
set_nonblocking(fd, 1);
result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
if( result == SOCKET_ERROR ) {
if (nonblocking && errno == EINPROGRESS) {
return fd;
}
if( !silent )
2c) before static int create_session ...
, add
/**
* For use with the non-blocking make_connection, add the fd to readfds
*/
int add_readfd(int fd, uint32 ip) {
#ifndef SOCKET_EPOLL
// Select Based Event Dispatcher
sFD_SET(fd,&readfds);
#else
// Epoll based Event Dispatcher
epevent.data.fd = fd;
epevent.events = EPOLLIN;
if( epoll_ctl( epfd, EPOLL_CTL_ADD, fd, &epevent ) == SOCKET_ERROR ){
ShowError( "make_connection: failed to add socket #%d to epoll event dispatcher: %s\n", fd, error_msg() );
sClose(fd);
return -1;
}
#endif
if (fd_max <= fd) fd_max = fd + 1;
create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
session[fd]->client_addr = ip;
return fd;
}
2d) In create_session
, change
sFD_CLR(fd, &readfds);// this needs to be done before closing the socket
to
if (sFD_ISSET(fd, &readfds))
sFD_CLR(fd, &readfds);// this needs to be done before closing the socket
2e) After sock2fd
, create a new function:
SOCKET fd2sock_ext(int fd) {
return fd2sock(fd);
}
3) In socket.hpp
, change
int make_connection(uint32 ip, uint16 port, bool silent, int timeout);
to
int make_connection(uint32 ip, uint16 port, bool silent, int timeout, bool nonblocking=false);
int add_readfd(int fd, uint32 ip);
3b) After void send_shortlist_do_sends();
, add
// Only for windows
#ifdef WIN32
SOCKET fd2sock_ext(int fd);
#endif
4) In atcommand.cpp
4a) add #include "disif.hpp"
near the top
4b) after
} else if (strstr(command, "attendancedb") || strncmp(message, "attendancedb", 4) == 0) {
attendance_db.reload();
clif_displaymessage(fd, msg_txt(sd, 795)); // Attendance database has been reloaded.
add
} else if (strstr(command, "discordconf") || strncmp(message, "discordconf", 4) == 0) {
reload_disif();
4c) after that function, add
/**
* disable discord
*/
ACMD_FUNC(disablediscord) {
stop_disif();
return 0;
}
4d) Add the commands
ACMD_DEF2("reloaddiscordconf", reload),
ACMD_DEF(disablediscord),
4e) at the end of ACMD_FUNC(request)
, add
disif_send_request_to_disc(*sd, message);
5) In channel.cpp
5a) Add #include "disif.hpp"
5b) In channel_send()
, after clif_channel_msg(channel,output,color);
add
if (channel->discord_id) {
safesnprintf(output, CHAT_SIZE_MAX, "%s : %s", sd->status.name, msg);
disif_send_message_to_disc(channel, output);
}
6) In channel.hpp
, in struct Channel
, after unsigned short *groups;
, add
uint64 discord_id; // Discord channel to forward to
7) In src/map/map-server.vcxproj
AND src/map/map-server-generator.vcxproj
7a) After <ClInclude Include="date.hpp" />
add
<ClInclude Include="disif.hpp" />
7b) After <ClCompile Include="date.cpp" />
add
<ClCompile Include="disif.cpp" />
8) In src/map/map-server.vcxproj.filters
AND src/map/map-server-generator.vcxproj.filters
8a) After
<ClInclude Include="date.hpp">
<Filter>Header Files</Filter>
</ClInclude>
add
<ClInclude Include="disif.hpp">
<Filter>Header Files</Filter>
</ClInclude>
8b) After
<ClCompile Include="date.cpp">
<Filter>Source Files</Filter>
</ClCompile>
add
<ClCompile Include="disif.cpp">
<Filter>Source Files</Filter>
</ClCompile>
9) In src/map/map.cpp
9a) Add #include "disif.hpp"
9b) After do_final_clif();
add
do_final_disif();
9c) Before npc_event_do_oninit();
add
#ifndef MAP_GENERATOR
do_init_disif();
#endif
10) In src/map/clif.cpp
10a) Add #include "disif.hpp"
10b) In void clif_parse_WisMessage()
Before
// searching destination character
dstsd = map_nick2sd(target,false);
add
else if (strcmpi(target, "@discord") == 0) {
disif_discord_wis(*sd, target, message);
clif_wis_end(fd, 0); // 0: success to send whisper
return;
}