Hello! You mentioned a juniors-focused discord server. Is it open to join?
Hi hi! The 18+ one I'm on is still open, yeah. The event one I'm making is open to join. I'm just having trouble with the bots, so roles are "ask to be assigned"

#dc comics#batman#dc#bruce wayne#dick grayson#tim drake#batfamily#batfam#dc fanart


seen from Saudi Arabia

seen from Italy

seen from United States

seen from United States
seen from United States

seen from Ukraine
seen from Poland
seen from United States
seen from Poland

seen from United States
seen from United States
seen from China
seen from Poland

seen from United Kingdom
seen from United States
seen from Australia

seen from Bulgaria
seen from China
seen from Indonesia
seen from United States
Hello! You mentioned a juniors-focused discord server. Is it open to join?
Hi hi! The 18+ one I'm on is still open, yeah. The event one I'm making is open to join. I'm just having trouble with the bots, so roles are "ask to be assigned"

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch β’ No registration required β’ HD streaming
THE KLARION COLLAB DISCORD IS OFFICIALLY OPEN TO PARTICIPANTS AND SPECTATORS!
Check out the π€Klarion Collab 2022!π€ community on Discord - hang out with 4 other members and enjoy free voice and text chat.
The event has officially begun folks! Come on and hop in!
The Discord Server is now open to the public!
https://discord.gg/Gx5wu2QXj6
Join the MHA Event Server! Event Art by yours truly!
Designing a Concurrent Application - The Event Server (part VIII)
Implementing the Status Messages
shutdown -> exit(shutdown); {'DOWN', Ref, process, _Pid, _Reason} -> loop(S#state{clients=orddict:erase(Ref, S#state.clients)}); code_change -> ?MODULE:loop(S); Unknown -> io:format("Unknown message: ~p~n",[Unknown]), loop(S)
The first case (shutdown) is pretty explicit. You get the kill message, let the process die. If you wanted to save state to disk, that could be a possible place to do it. If you wanted safer save/exit semantics, this could be done on every add, cancel or done message. Loading events from disk could then be done in the init function, spawning them as they come.--book
The 'DOWN' message's actions are also simple enough. It means a client died, so we remove it from the client list in the state.--book
Unknown messages will just be shown with io:format/2 for debugging purposes, although a real production application would likely use a dedicated logging module--book
And here comes the code change message. This one is interesting enough for me to give it its own section.--book

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch β’ No registration required β’ HD streaming
Designing a Concurrent Application - The Event Server (part VII)
Implementing the Event Timing Out Message - reminder fire away
the events timing out. That message is simply {done, Name}:--book
{done, Name} -> case orddict:find(Name, S#state.events) of {ok, E} -> send_to_clients({done, E#event.name, E#event.description}, S#state.clients), NewEvents = orddict:erase(Name, S#state.events), loop(S#state{events=NewEvents}); error -> %% This may happen if we cancel an event and %% it fires at the same time loop(S) end;
And the function send_to_clients/2 does as its name says and is defined as follows:--book
send_to_clients(Msg, ClientDict) -> orddict:map(fun(_Ref, Pid) -> Pid ! Msg end, ClientDict).
Designing a Concurrent Application - The Event Server (part VI)
Implementing the Client Message - cancel (cancel a reminder)
The next message defined in our protocol is the one where we cancel an event. Canceling an event never fails on the client side, so the code is simpler there. Just check whether the event is in the process' state record. If it is, use the event:cancel/1 function we defined to kill it and send ok. If it's not found, just tell the user everything went right anyway -- the event is not running and that's what the user wanted.--book
{Pid, MsgRef, {cancel, Name}} -> Events = case orddict:find(Name, S#state.events) of {ok, E} -> event:cancel(E#event.pid), orddict:erase(Name, S#state.events); error -> S#state.events end, Pid ! {MsgRef, ok}, loop(S#state{events=Events});
Designing a Concurrent Application - The Event Server (part V)
Implementing the Client Message - add (adding a reminder)
{Pid, MsgRef, {add, Name, Description, TimeOut}}
The next message to care about is the one where we add events. Now, it is possible to return an error status. The only validation we'll do is check the timestamps we accept. While it's easy to subscribe to the {{Year,Month,Day}, {Hour,Minute,seconds}} layout, we have to make sure we don't do things like accept events on February 29 when we're not in a leap year, or any other date that doesn't exist. Moreover, we don't want to accept impossible date values such as "5 hours, minus 1 minute and 75 seconds". A single function can take care of validating all of that.--book
The first building block we'll use is the function calendar:valid_date/1. This one, as the name says, checks if the date is valid or not. Sadly, the weirdness of the calendar module doesn't stop at funky names: there is actually no function to confirm that {H,M,S} has valid values. We'll have to implement that one too, following the funky naming scheme:--book
valid_datetime({Date,Time}) -> try calendar:valid_date(Date) andalso valid_time(Time) catch error:function_clause -> %% not in {{Y,M,D},{H,Min,S}} format false end; valid_datetime(_) -> false. valid_time({H,M,S}) -> valid_time(H,M,S). valid_time(H,M,S) when H >= 0, H < 24, M >= 0, M < 60, S >= 0, S < 60 -> true; valid_time(_,_,_) -> false.
Now on to implementing the add message with datetime valid function:
{Pid, MsgRef, {add, Name, Description, TimeOut}} -> case valid_datetime(TimeOut) of true -> EventPid = event:start_link(Name, TimeOut), NewEvents = orddict:store(Name, #event{name=Name, description=Description, pid=EventPid, timeout=TimeOut}, S#state.events), Pid ! {MsgRef, ok}, loop(S#state{events=NewEvents}); false -> Pid ! {MsgRef, {error, bad_timeout}}, loop(S) end;
If the time is valid, we spawn a new event process, then store its data in the event server's state before sending a confirmation to the caller. If the timeout is wrong, we notify the client rather than having the error pass silently or crashing the server. Additional checks could be added for name clashes or other restrictions (just remember to update the protocol documentation!)--book