mafia.gg bot
but why
why would you want a dis- BEEP
you will need:
- a mafia.gg account
- a mongodb account
in the mongodb acc make a new cluster
click on connect
click on use for application
in dropdowns select python 3.8.6
copy the url
in the new cluster make a collection called "mafiagg"
clone this repo
execute pip3 install mafapi
edit config.py
put your username
put your password
in MONGODB, put the url you copied earlier
execute main.py
you're done
scroll to the bottom.
url | post data | get data | usage |
---|---|---|---|
https://mafia.gg/api/user-session | {login: str, password: str} | {id: USERID, username: USERNAME, email: EMAIL, hostBannedUsernames: [???], isPatreonLinked: true/false, activePatreon: true/false, needsVerification: true/false, createdAt: 'yyyy-mm-ddThh:mm:ss:pppZ'} | used to login to an account, use the cookies |
https://mafia.gg/api/rooms | [{id: ROOMID, name: ROOMNAME, hasStarted: true/false, playerCount: int, setupSize: 12, hostUser: {id: USERID, username: USERNAME, activepatreon: true/false, createdAt: 'yyyy-mm-ddThh:mm:ss:pppZ'}, createdAt: 'yyyy-mm-ddThh:mm:ss:pppZ'}] | get list of all rooms | |
https://mafia.gg/api/rooms/ROOMID | {engineUrl: URL, auth: AUTH} | get data about specific room, URL is the engine url, AUTH is the authentication token | |
https://mafia.gg/api/rooms/ROOMID/kick | {userId: USERID} | kick specific user from room | |
https://mafia.gg/api/users/USERID | {id: USERID, username: USERNAME, activepatreon: true/false, createdAt: 'yyyy-mm-ddThh:mm:ss:pppZ', ?type: 'admin'} | get data about specific user, specifically id, username, activePatreon, createdAt | |
https://mafia.gg/api/decks?filter&page=PAGENUM | {pagination: {page: PAGENUM, numPages: 12, total: 290}, decks: [{name: DECKNAME, version: VERSION, key: DECKID, builtin: true/false, deckSize: int, uploadTimestamp: UNIXTIMESTAMP, sampleCharacters: [{playerId: int, name: str, avatarUrl: str, backgroundColor: '#rrggbb'}]}]} | get data about all decks on specific page | |
https://mafia.gg/api/decks/DECKID | {name: DECKNAME, version: VERSION, key: DECKID, builtin: true/false, deckSize: int, uploadTimestamp: MILLIUNIXTIMESTAMP, characters: [{playerId: PLAYERID, name: str, avatarUrl: str, backgroundColor: '#rrggbb'}]} | get data about a specific deck |
url | request type | data | usage |
---|---|---|---|
https://mafia.gg/api/user | PATCH | {email: EMAILADDR, timeFormat: 'time'/???, hostBannedUsernames: [USERNAME], password: str, passwordConfirmation: str, patreonCode: null/???, } | the settings changed by this page |
???s are the parts i haven't figured out yet.
type | data (from server) | data (to server) | usage |
---|---|---|---|
clientHandshake | {events: [PACKET], possibleUserIds: [???], sid: ?, timestamp: UNIXTIMESTAMP, users: [{userId: USERID, isHost: ISHOST, isPlayer: ISPLAYER}]} | {userId: USERID, roomId: ROOMID, auth: AUTHTOKEN} | FIRST PACKET TO SEND, starts communication between client and server |
ping | client -> server | ||
pong | {timestamp: UNIXTIMESTAMP, sid: SID} | server -> client | |
chat | {message: MESSAGE, from: {model: 'user'/'player', userid: USERID/0, playerid: PLAYERID}, timestamp: UNIXTIMESTAMP, sid: SID} | {message: MESSAGE} | send message through the chatroom |
newGame | {roomId: ROOMID} | SAME AS FROM SERVER | create a new room |
options | {dayLength: 1-9, dayStart: 'off'/'dawnStart'/'dayStart', deadlockPreventionLimit: '-1'/???, deck: '-1'/DECKID, disableVoteLock: true/false, hideSetup: true/false, hostRoleSelection: true/false, majorityRule: '-1'/'51'/???, mustVote: true/false, nightLength: 1-9, noNightTalk: true/false, revealSetting: 'allReveal'/???, roles: ROLES, roomName: ROOMNAME, scaleTimer: true/false, twoKp: '0'/???, unlisted: true/false | SAME AS FROM SERVER | set the options of the room |
startGame | starts the game | ||
decision | {details: {text: 'votes'/???, playerId: PLAYERID, targetPlayerId: PLAYERID, }, groupId: ???, id: ???, qid: ???, sid: SID, timestamp: UNIXTIMESTAMP} | voting AFAIK, prob more | |
decisionGroup | {id: ???, kind: 'vote'/???, label: 'Condemn'/???, timestamp: UNIXTIMESTAMP} | the packet to make the tiny box appear on the screen | |
alert | {timestamp: UNIXTIMESTAMP} | ||
system | {timestamp: UNIXTIMESTAMP, message: MESSAGE} | a message from the mafia game system to the client | |
time | {phase: 'day'/'night', ordinal: number, timestamp: UNIXTIMESTAMP | when a phase begins: DAY 2, NIGHT 1, etc... | |
timer | {end: UNIXTIMESTAMP, timestamp: UNIXTIMESTAMP, topic: TOPIC} | the topic is stuff like "Free period", "End-of-night buffer" and such | |
quote | {qid: ???, timestamp: UNIXTIMESTAMP, from: {model: 'user'/'player', userId: USERID/0, playerId: PLAYERID}} | quotes in the chat | |
death | {playerId: PLAYERID, timestamp: UNIXTIMESTAMP} | death | |
userJoin | {userId: USERID, isHost: bool, isPlayer: bool, timestamp: UNIXTIMESTAMP, sid: SID} | a user joining | |
userQuit | {userId: USERID, timestamp: UNIXTIMESTAMP, sid: SID} | a user exiting | |
transferHost | {userid: USERID} | transfer host to specific player | |
endGame | {roles: {PLAYERID (int): ROLEID (int)}, sid: SID, timestamp: UNIXTIMESTAMP, users: {USERID (int): PLAYERID (str)}} | marks the end of a game, shows who was who bc of decks, and shows everyone's roles | |
optionsSetup | {roles: ROLES, sid: SID, timestamp: UNIXTIMESTAMP} | purpose unknown to me |
type | format | usage |
---|---|---|
USERID | str | use with the users api to find name |
PLAYERID | str | use the decks api, and find the card with the playerid |
ROOMID | str | use with the rooms api |
UNIXTIMESTAMP | int | the unix time stamp, in seconds |
MILLIUNIXTIMESTAMP | int | the unix time stamp, in milliseconds |
MESSAGE | str | a message |
ROOMNAME | str | the name of a room |
TOPIC | str | the topic of a room |
PACKET | object | see above table |
ROLES | object | {ROLEID: ROLEAMO, ROLEID: ROLEAMO, ....} |
ROLEID | str | the id of a role, found in a setup code |
ROLEAMO | str | amount of times a role appears, capped to 99 by the mafia.gg GUI, if it goes over, shows as the last number below 99 |
SID | int | this number MUST increase every time it is sent. |
key | api values | gui values |
---|---|---|
dayStart | off, dayStart, dawnStart | off, uninformed, informed |
deck | -1 | no deck |
majorityRule | -1, 51 | no majority, simple majority |
copy and paste this script into chrome devtools, then do stuff while satching the console.
open up chrome devtools using F12, use Ctrl+F5 to refresh the page and cache, go into the devtools and click on network, you should see something like this:
right now, the only requests that you should be looking at are all the requests labeled "xhr", one of them is the "rooms" request, click on it and you'll see
you can ignore the general and response headers sections, look at the request headers (in this case you can ignore it, but thats the exception to the rule,) another thing you should look at is the response, click preview
as you can see, those are all the rooms you can see on the page, in json format! this is how i figured out all the ordinary api requests.
same as with api, but you must enter a game first, and you'll see this:
the "engine" request is the only important thing here, this applies to all websocket packets here. click on it.
you can ignore the headers for all websocket packets, just click on messages and you'll see this:
each of these rows is a different packet: red arrows pointing down are the packets from the server, to the client; green arrows pointing up are the packets from the client, to the server.