DAmn
- The correct title of this article is dAmn. The initial letter is capitalized due to technical limitations.
dAmn (the deviantART Message Network, or deviantART Messaging Network) is deviantART's real-time messaging network. Since its beginning, it has become one of the most popular communication features of deviantART.
Contents
History
- This section is a stub. You can help Botdom Documentation by expanding it by clicking the edit button at the right.
dAmn was launched on August 7, 2004, when deviantART upgraded to version 4.
Official client
- This section is a stub. You can help Botdom Documentation by expanding it by clicking the edit button at the right.
dAmn's official client is run in a web browser using either a Mozilla Firefox extension, Flash or Java, and accompanied with JavaScript. The client is present at the chat subdomain of deviantart.com.
Authtokens
Any clients wishing to connect to dAmn need to provide an authtoken in the login packet. More information on this can be found here.
Tablumps
dAmn uses tablumps to format different elements in the chat. More information can be found at this page.
Protocol
dAmn has a raw protocol system, which makes building a bot much easier. dAmn runs on chat.deviantart.com
(54.68.114.41
), TCP port 3900.
This section aims to guide you through the protocol and each packet that you can send or receive. Everything is seen from the client's point of view. All characters will be spelled out in this guide, however in languages like PHP, you might need to type \n
instead of line breaks seen in packets. Variables will be shown in bold italics in the code. We will show every variable's meaning (unless it's already shown in a paragraph before or the meaning is very obvious). Optional parts are displayed in a grey color.
Basic packet format
Basic Explanation
The basic format of a dAmn packet looks like this:
packetname mainparam some=variables somemore=variables (Any characters can be used here) Main content is placed here.
Where mainparam
is a parameter that's very relevant to the packet's subject, e.g. a username or chat room. Also, as said, remember that all packets end in a pure NULL
character which is sometime represented as \0
, \000
, \0x00
or <php-inline>chr(0)</php-inline>. Most packets also need a line feed (aka Unix line break \n
) before the NULL, however packets where the last part is distributed to the chat room (the send
packet being the best example) do not need this.
If you used \n
instead of line breaks, the example packet above would look like this:
packetname mainparam\nsome=variables\nsomemore=variables (Any characters can be used here)\n\nMain content is placed here.
In raw format, chat room names are formatted chat:name
where name is the name of the chat room. Private chat room names are formatted pchat:user1:user2
where user1 and user2 are the names of the users who are in the private room. The usernames are sorted alphabetically, so e.g. "Albert" would go before "Zack".
Official Way
While looking at the source code for the official client, This is how it is officially broken down:
cmd param arg1=value1 arg2=value2 body
Some packets insert a sub-packet into the body (recv is one of them) and those sub-packets are formatted (and can be parsed by the official parser) just like their enclosing packet. There are times when a sub-packet will contain only arguments and a body and not have the cmd/param at the start. Also, param is optional. See dAmn Packet Parser for an example of an easy way to parse packets.
Grammar
For those of you who like having grammars to work with, here is a simple thing based on the notation used at Python.org. <bnf> key ::= <any character excluding argument_separator, whitespace, and null>* value ::= <any character excluding newlines and null>* body ::= <([^\0])>* command ::= key parameter ::= value
cmdline ::= command [ " " parameter ] "\n" argument_separator ::= "=" | ":" argument ::= key argument_separator value "\n" packet ::= ( [ cmdline ] argument+ | cmdline ) [ "\n" body ] "\0" </bnf>
The below should describe things in more detail, with relation to sub-packets. <bnf> sub_packet ::= ( [ cmdline ] argument+ | cmdline ) [ "\n" body ] packet ::= cmdline argument* "\n" [ body ] "\0" </bnf>
In "BNF" format: <bnf>
<packet> ::= [ <cmdpair> ] <args>* [ <body> ] '\NUL' <cmdpair> ::= <command> [ ' ' <param> ] <newline> <args> ::= <argkey> '=' <argvalue> <newline> <body> ::= <newline> <command> ::= <alpha>+ <param> ::= ( <alpha> | '-' | ':' | '.' | <number> )+ <argkey> ::= <alpha>+
<argvalue> ::= ( '\x01'...'\x09' | '\x0B' | '\x0C' | '\x0E'...'\xFF' )+
::= ( '\x01'...'\xFF' )* <alpha> ::= 'A'...'Z' | 'a'...'z' <number> ::= '0'...'9' <newline> ::= '\n'
</bnf>
Client packets
These are the packets that go from the client to the server.
dAmnClient (handshake)
This packet performs the initial handshake with the server before you continue logging in.
dAmnClient version agent=agent optionalparameter=value value optionalparameter2=value
The variable version is the version of the protocol which you are going to use. Only the newest version will work, if you use an older version, you will get disconnected. The current protocol version that is used is 0.3 (as of April 8 2008).
The agent variable is required. This is used to tell the server which kind of client/agent is used to connect to the server. Examples could be dAmn WebClient 0.7.pre-1
or futurism/beta 0.3
. It is not your deviantART username. In addition to this, you can set any other variable you want. It is unknown whether the server takes action on these variables or saves them anywhere. In 0.1, variables weren't available in this packet.
You have to wait for a dAmnServer (handshake response) packet before you can continue logging in.
login
After handshaking, you use this packet to log in to the server.
login username pk=authtoken
The username being the username you want to log in with, obviously, and the authtoken being your user account's dA authtoken. This is a hash value which changes every time you log in (unless you're using reusetoken) or log out. When you've logged in, you can see it in the cookie you receive from deviantART. In Firefox, this can be done by going to Tools > Settings > Privacy > View cookies and browsing. The cookie is a URL encoded list of variables, and the authtoken is one of those. It can also be seen in the source code when using the official dAmn client. Look for this: dAmn_Login( "username", "authtoken" );
After sending this packet, you have to wait for a server login packet in return before you can continue.
join
To join a chat room, send this packet:
join chat:chatroom
Very simple. chatroom is of course the name of the chat room you wish to join. To join a private chat, send this packet:
join pchat:user1:user2
Again very simple, the two users are the names of the users who should chat, which means one of those are you. They are sorted alphabetically.
part
Parting a chat room is almost the same as above:
part chat:chatroom
part pchat:user1:user2
pong
This is a very simple packet. As you'll learn later, the server occasionally sends a ping packet to check your connection. When it does that, simply return with this packet:
pong
However, if you want, you can also send this packet whenever you wish.
send
Here we're getting to what you may call the real stuff! You use this packet to send messages to a chat room. Mainly, there are three types of messages which you can send, which are defined by the middle part of the packet. (Actually, the send packet is used for many things, but we're going to cover the message related actions in this section.)
Based on testing done by doofsmack, it seems that if the message sub-packet (anything after the send chat:chatroom
) is larger than 8192 bytes, the message is rejected and you are disconnected. All your sent messages are received back like all the other messages, so there's no need to show the message when sending it.
msg
This is the "ordinary" one that sends a normal message.
send chat:chatroom msg main content
Again, chatroom is the chat room in which you want to say something. As in all other places, it can also be in the pchat:user1:user2
format. And the content variable is simply the stuff you want to send!
action
Other than using the send command to send messages, you also use it for /me actions. This only requires a slight change in the packet:
send chat:chatroom action main content
Which will output /me content
.
npmsg
And the last thing you can send is the npmsg (non parsed message) type:
send chat:chatroom npmsg main content
Non parsed messages don't contain anything that is parsed (like tags, emoticons, etc.) That's what you send when you hold the shift button while entering your message on the official dAmn client.
promote
Now that we've really gotten into it, we'd like to do more! Here's the packet you use to promote people:
send chat:chatroom
promote username
privclass
In this one, username is the name of the user you want promoted. If you specify a privclass, the user will go directly to that privclass if you have the privileges to do so. If you don't specify any, the person will be promoted to the privclass directly above the one he's currently in.
demote
Demoting is basically the same procedure as above.
send chat:chatroom
demote username
privclass
Again, username being the name of the user you want promoted. If you specify a privclass, the user will go directly to that privclass if you have the privileges to do so. If you don't specify any, the person will be demoted to the privclass directly below the one he's currently in.
ban
And if the annoying guys just keep coming back, you can ban them from the chatroom with this packet:
send chat:chatroom ban username
This will ban username from chatroom. Note: One line break is required at the end
unban
This is basically the same as ban.
send chat:chatroom unban username
This will promote (or demote) username from chatroom to the guest privclass, even if he wasn't originally banned.
kick
You can kick people out from the room (if you have sufficient privileges) with this packet:
kick chat:chatroom
u=username
reason
This will kick username from chatroom with the reason reason. The reason can be empty.
get
property
Use this command to receive properties for a special room if you haven't already received them.
get chat:chatroom p=property
Where property can be either title, topic, privclasses or members. It will then send you a property packet in return. You should receive those automatically when you join a room, but you can use this command to request them again.
userinfo
You can also use this packet to get information about a user.
get login:username p=info
This will return a property packet with the information you'll need to know about username and its connection to dAmn. This is the equivalent of doing a /whois on dAmn.
set
Now that you know how to get a property, this packet lets you set a property:
set chat:chatroom p=property value
This sets the property (which can be either title or topic) to value in chatroom if you have sufficient privileges.
admin
This packet lets you perform admin commands if you have the privileges, just like the /admin command or chatroom settings window in the official dAmn client:
send chat:chatroom admin command
Where command is the admin command you want to execute. Example: update privclass Members +smilies.
disconnect
This packet allows you to quit dAmn gracefully. It asks the server to disconnect you. The server replies with a part packet per room the user is joined to, followed by a disconnect packet.
disconnect
All rooms that you leave will show your reason for leaving as "quit".
Based on testing done by plaguethenet it appears that you cannot set the reason for disconnecting.
kill
This packet is used by dAmn admins to kill a connection.
kill login:username
reason
The reason is optional. If username doesn't exist or is not online, or if you do not have the required privileges, you receive an error packet with the reason why it didn't work.
Server packets
This are the packets that go from the server to the client.
dAmnServer (handshake)
This is the server's reply packet to your dAmnClient handshake packet.
dAmnServer version
This packet is very simple. If the dAmn protocol version which you selected in your dAmnClient packet is supported by the server, it will return it here in the variable version. If you received this packet, you successfully handshaked and you're ready to log in!
login
When you've send your log in packet, the server will respond with this packet.
login username e=event symbol=symbol realname=Deviants Supplied Name typename=Type of Artist gpc=Server Privs
This packet will simply tell you whether your login as username was successful. We know of these values which event can have:
- ok
- Your login was successful!
- authentication failed
- Your username / authtoken combination wasn't correct.
- not privileged
- Unfortunately, you've been banned from the dAmn service.
- too many connections
- You have too many connections open (Limit is 20 connections per username.)
Furthermore, this packet also sends information about the account you're logging into. The values of symbol, realname, and typename are self-explanatory. In almost all instances gpc will equal guest unless you are a dAmn admin.
join
When you try to join a room, you'll receive this packet in return.
join chat:chatroom e=event
event determines whether your join was successful. We know of these values event can have:
- ok
- You've successfully joined chatroom.
- not privileged
- You're banned from this room, or it's a private room.
- chatroom doesn't exist
- Self-explanatory. The room you're trying to join doesn't exist.
- bad namespace
- The name of the room you are trying to join uses bad characters that can't be in a room name.
Like everywhere else, the chatroom variable can also be in the pchat:user1:user2
format.
part
Like above, when you've tried to part a room, you'll receive this packet in return which determines whether your part was successful.
part chat:chatroom
e=event
r=reason
We know of these values event can have:
- ok
- You've successfully parted chatroom.
- not joined
- You haven't joined this room.
- bad namespace
- The name of the room you are trying to part uses bad characters that can't be in a room name.
In addition, there's also a reason parameter, which appears when you've been forced to part by the server or a Message Network Administrator. We know of these values reason can have:
- bad msg
- You were disconnected because your message had characters that are not supported, or your sub-packet wasn't correct.
- bad data
- You sent a packet that can't be used or doesn't exist.
- msg too big
- The message you were trying to send was longer than 8192 bytes.
- killed: reason
- A message network administrator closed your connection with reason.
property
This packet is sent by the server to set an object's property.
property chat:chatroom p=property by=who set the topic/title ts=time topic/title was set value
This assigns value to chatroom's property. We know of these values property can have:
- topic
- chatroom's topic.
- title
- chatroom's title.
- privclasses
- chatroom's privclasses.
- members
- The list of people currently in chatroom. Includes the same information present in the join packet that's a subpacket of recv.
- login:username
- Whois information for username.
We'll write more about each property in a later section. You usually get the first four properties when you join a room, but they can also be received using the get packet. The last one is request-only.
whois
This packet is the server's whois packet
property login:username p=info usericon=usericon symbol=symbol realname=realname typename=typename gpc=global privs conn online=seconds online idle=seconds idle ns channel ns channel conn online=seconds online idle=seconds idle ns channel ns channel etc.
This packet is relatively easy to parse, ns and channel require special handling, but each conn subpacket is a seperate connection.
It should also be noted that this packet will not show pchats that the user has joined, only chats from the normal namespace will be included.
recv
This is where stuff really happens! You use this server packet to receive messages of many kinds, determined by the value part of the packet.
msg
This is the packet you use to receive ordinary messages.
recv chat:chatroom msg main from=username content
This indicates that username has said content in chatroom. (And of course chatroom can be in the pchat:user1:user2
format.) When you send npmsgs, they will also end up here, however with unparsed emoticons and tags (which are html encoded with >, <, &, etc).
action
This is the packet you use to receive /me actions.
recv chat:chatroom action main from=username content
This indicates that username has content'd in chatroom.
join
This is the packet you receive when someone else joins one of the rooms you are in.
recv chat:chatroom join username s=show pc=privclass usericon=icon symbol=symbol realname=realname typename=typename gpc=gpc
This indicates that username has joined chatroom; show is either a 1 or 0 indicating whether the client should display a join notification. Furthermore, this packet will also send you information about username in the body.
The body is a subpacket which contains nothing but arguments, most of them self-explanatory. privclass is the user's privclass in the chatroom, icon is the icon number of the user, symbol is the user's symbol, realname is the user's tag line set on their profile page, typename is the type of deviant the user set themselves as on their profile page, and gpc is the global privclass of the user. The global privclass indicates if the user is a normal deviant ("guest") or if they have administrator privileges (such as "MN@ Operator"). The icon number indicates two things: the extension of the avatar and the cache buster to use when requesting it. This is the algorithm, as displayed using simplified code directly from the official dAmn client (JavaScript), to calculate both of these:
<javascript> dAmn_avatar_ext = [ '.gif', '.gif', '.jpg', '.png' ];
cachebuster = (icon_number >> 2) & 15; extension = dAmn_avatar_ext[ icon_number & 3 ]; </javascript>
part
Like above, this is the packet you receive when someone else parts one of the rooms you are in.
recv chat:chatroom
part username
r=reason
This indicates that username has parted chatroom with or without a reason. If it's blank, the user has only parted this chatroom, but still has a connection open. If there's a reason, username's connection was also closed at the same time as the part happened. We know of these values reason can have:
- connection closed
- The user closed connection.
- connection reset
- The user's connection was reset.
- timed out
- The user didn't respond to the server after a while, and was disconnected by the server.
- bad msg
- The message had characters that was not supported or sent an incorrect sub-packet, and was disconnected by the server.
- bad data
- The user sent a packet that can't be used or doesn't exist, and was disconnected by the server.
- msg too long
- The message which the user was trying to send was too long, and the user was disconnected by the server.
- send error
- We still don't know for sure what this means. We're guessing miscellaneous error that doesn't fall into any other category.
- quit
- the user gracefully disconnected from the server. (See disconnect)
- killed: reason
- A message network administrator closed the users connection with reason.
privchg
This is the packet you receive when someone gets promoted, demoted, banned or unbanned.
recv chat:chatroom privchg username by=username2 pc=privclass i=show
This indicates that username was moved to privclass by username2. show indicates whether the client should display a notification, and is either 0 or 1.
kicked
This is the packet you receive when someone else gets kicked.
recv chat:chatroom
kicked username
by=username2
i=show
reason
This indicates that username has been kicked from chatroom by username2 with reason, which can be empty. show indicates whether the client should display a notification, and it either 0 or 1.
admin
This is the packet you receive when someone does admin commands. They are different for each admin command. If the order of the privclasses in a room is changed the server sends a privclass property packet along with the admin packet.
create & update
This is the packet you receive when someone creates or updates a privclass.
recv chat:chatroom admin action p=privclass by=username name=privclassname privs=privileges
(With action being either create
or update
) This indicates that username created or updated the privclass privclassname with the privs privileges in chatroom.
rename & move
This is the packet you receive when someone renames a privclass or moves all users from one privclass to another.
recv chat:chatroom
admin action
p=privclass
by=username
prev=previousprivclassname
name=privclassname
n=usersaffected
If action is rename
, then this indicates that username renamed the privclass previousprivclassname to privclassname. If the action is move
, then this indicates that username moved all users from the privclass previousprivclassname to privclassname, and the original privclass still exists. The parameter usersaffected then shows how many deviants were actually moved in the admin action. This parameter only exists if action is move
.
remove
This is the packet you receive when someone removes a privclass.
recv chat:chatroom admin remove p=privclass by=username name=privclassname n=usersaffected
This simply indicates that username removed the privclass privclassname, and that usersaffected users were affected by this.
show
This is the packet you recieve when you send the admin command show. For privclasses you get this:
recv chat:chatroom admin show p=privclass privclassname privs
This does not need to be parsed and can be directly displayed. It is already preformatted.
If you send the admin command show users then you will get this:
recv chat:chatroom admin show p=users privclassname: user1 user2 .... userN privclassname: user1 user2 .... userN
This is also already formatted.
privclass
This is an error packet received after attempting to use the admin command in a channel.
recv chat:chatroom admin privclass p=action e=error command
command is the admin command that was sent by the client.
kicked
This is the packet you receive if you get kicked (not if anyone else does).
kicked chat:chatroom
by=username
reason
This indicates that username kicked you from chatroom with the reason reason, which can be empty.
ping
To check your connection, the server will send you the ping packet.
ping
When you receive this packet, it is required that you send a pong packet in return, or you will be disconnected (timed out) by the server. The time it waits before disconnecting you seems to be 48 seconds. If there is no successful interaction between your client and the server within 96 seconds then it is likely that your client has been disconnected from the server. However, the maximum time it usually takes for a connection to time out appears to be around two minutes.
disconnect
This is the packet you receive if you fail to connect (or end up disconnecting) to the dAmn service somehow.
disconnect e=event
event indicates why you were disconnected. We know of these values event can have:
- ok
- The server has accepted your request to quit gracefully.
- killed
- You were killed by a message network administrator.
- no login
- You failed to start the connection process by handshaking and/or logging in.
- shutdown
- The server is temporarily shutting down. All users get disconnected.
Error packets
This is a list of server packets which are only used to report errors with client packets.
send
This is the packet you receive if an error occurs during a client send packet.
send chat:chatroom e=event
event specifies what the error is. We know of these values event can have:
- nothing to send
- You're trying to send an empty message.
- not privileged
- There could be many reasons for this. Either you don't have privileges to do what you're trying to do, or you haven't joined the room in which you're trying to do something.
- not open
- You're trying to do something in a room that no one's in.
- format error
- There is a slight error in your packet syntax, but not a huge error, such as missing line breaks at the end.
- bad command
- The sub-packet you were trying to send was incorrect for this type of room.
kick
This is the packet you receive if an error occurs during a client kick packet.
kick chat:chatroom u=username e=event
event specifies what the error is. We know of these values event can have:
- no such member
- The user you're trying to kick isn't in the room, or you haven't joined the room in which you're trying to kick.
- not privileged
- You don't have +kick privileges, or the user you're trying to kick is in a class above you, is the creator of the room or is a Message Network Administrator.
get
This is the packet you receive if an error occurs during a client get packet.
get chat:chatroom p=property e=event
event specifies what the error is. We know of these values event can have:
- not joined
- You're trying to get a property for a room you haven't joined.
- unknown property
- This property doesn't exist.
set
This is the packet you receive if an error occurs during a client set packet.
set chat:chatroom p=property e=event
event specifies what the error is. We know of these values event can have:
- not joined
- You're trying to set a property for a room you haven't joined.
- unknown property
- This property doesn't exist.
- not privileged
- You don't have permission to set this property.
kill
This is the packet you receive if you send a kill packet with a malformed namespace.
kill login:username e=event
event specifies what the error is. We know of these values event can have:
- bad namespace
- The username you specified does not exist or is not on dAmn.
- not privileged
- You don't have permission to kill the specified login, Which in most cases is true unless you're MN@.