DAmn

From Botdom Documentation
Jump to: navigation, search
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.

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' )+

   <data> ::= ( '\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 &gt;, &lt;, &amp;, 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@.