Hangupsbot is a bot designed for working with Google Hangouts.
- Mentions: If somebody mentions you in a room, receive a private hangout from the bot with details on the mention, including context, room and person who mentioned you.
- Syncouts: A syncout is two Hangout group chats that have their messages forwarded to each other, allowing seamless interaction between the two rooms. Primarily used to beat the 150 member chat limit, but it can also be used for temporarily connecting teams together to interact.
- Hubot Integration: Hangupsbot will allow you to connect to Hubot, instantly providing you access to hundreds of developed chat tools and plugins.
- Lookups: Google Sheets can be attached to the bot, which allows you to look up data in the spreadsheet instantly with just a few keywords.
- Pushbullet API: Pushbullet is integrated.
- Hooks and Sinks: The bot has instructions for developing and attaching your own hooks and sinks, allowing the bot to interact with external services such as your company website, Google API's and much more.
- And many additional features! Eastereggs, games, nickname functionalities, the list goes on!
- To execute:
python3 hangupsbot.py
- Any current tests will be in
<path of hangupsbot.py>/tests/
- Please see the original documentation which is reproduced below (after the TODO section)
Install python 3.4 from source
wget https://www.python.org/ftp/python/3.4.2/Python-3.4.2.tgz
tar xvf Python-3.4.2.tgz
cd Python-3.4.2
./config
make
make install
Install dependencies
pip3 install -r requirements.txt
- You need to open a 1-on-1 conversation with the bot first and say "hello" (or anything!)
- Then give yourself a @mention in another HO where the bot is participating as a group member
This procedure is necessary to let the bot know you're alive ;P No seriously, the above steps are required to authorise two-way communication between the bot and your own account.
Some general rules:
- If
mentionquidproquo
is ON, only users who have already said something to the bot in private will be able to @mention others. - If a @mention matches multiple users, the bot will privately warn the user that too many users were selected. A list of all matching users will be provided as a guide to the user.
- A @mention must be at least 3 characters or longer (not counting the
@
)
A @mention matches the following:
- A part of the combined first name and last name of the user
e.g.
@abc
matchesAB Chin
(bot seesabchin
) - A part of the combined first name and last name with spaces replaced by
the underscore
e.g.
@ab_c
matchesAB Chin
(bot seesAB_Chin
) - An exact match with a user nickname, if the user has previously has
previously
/bot set nickname abc
e.g.@abc
matches nicknameabc
but NOT nicknamesabcd
orzabc
config.json
is found in two places:- one folder below
hangupsbot.py
;and later, - ...in
/root/.local/share/hangupsbot/
after first successful run
- one folder below
- add (or replace) your user id into the
admins
array in config.json
{
"admins": [
"104821221116551390464"
],
"autoreplies": [
...
To find out how to get your user id, read on!
- start the bot with a valid gmail account (not your actual account!)
- open a hangout with the bot (using your actual account), say anything to it
- login into the bot's gmail account and ensure chat is activated
- open up invites, and accept your incoming invite (from your actual account)
- restart the bot and it will dump out a conversation and users list
- find your actual account user name, the chat_id will be listed next to it
join a group with an existing bot and issue this command /bot whoami
, your
chat_id will be displayed
Configuration directives can be specified in config.json
.
Most configuration directives can be specified globally or per-conversation.
- Global directives are always specified in the "root" of
config.json
. - To specify a per-conversation directive, the same configuration option should
be defined as
config.conversations[<conversation-id>].<configuration option>
. - Per-conversation directives override global settings, if both are set.
mentionquidproquo
- default:
true
- only users who have already initiated a 1-on-1 dialog with the bot will be able to use @mentions and alert other users
mentionerrors
- default:
false
- outputs any problems with a @mention to the current conversation
- verbose output and should only be used for debugging
- alternative is to use
/bot mention <name-fragment> test
(see bot command below)
mentionall
- default:
true
- enables/disables @all for mentions
- when set to
false
, admins and chat ids listed inmentionallwhitelist
can still use @all - users who are blocked from using @mentions (
mentionall == false
; not an admin; not whitelisted) will be notified privately if the bot already has a 1-on-1 with them
mentionallwhitelist
- default:
[]
- allow listed chat_ids to use @all in mentions regardless of
global/per-conversation
mentionall
setting
Chats can be synced together, called a 'Syncout'. If a person says something in chat A, that message will be relayed into chat B by the bot, and vice versa, allowing multiple rooms to have conversations with each other. The primary use for this is to have more than 150 (the hangout limit) users talking to each other in the same room.
syncing_enabled
- default: false
- If enabled, will look for synced rooms and start relaying chats across the rooms
- Can only be enabled/disabled globally
sync_rooms
- a list of group ChatID's that the bot will attempt to keep synced
- it is possible to have more than one syncout instance per bot by having in your config.json:
"CONV1_ID": {
"sync_rooms": ["CONV1_ID", "CONV2_ID", ...]
},
"CONV2_ID": {
"sync_rooms": ["CONV1_ID", "CONV2_ID", ...]
},
"CONV3_ID": {
"sync_rooms": ["CONV3_ID", "CONV4_ID", ...]
}
- NOTE: You will have to put the convID into the sync_room of that convID too (to allow for backward compatibility with a deprecated method). I know that this is highly redundant for now, but stick to this method and you won't have any problems in the future when the code is improved (I hope).
Special /me
triggers are available to any user.
All these must be prefixed by /me
, as in /me <trigger>
.
roll[s] [a] dice
- Bot will (virtually) roll a dice and return the number 1-6
flip[s] [a] coin
- Bot will (virtually) flip a coin and return heads or tails.
draw[s] [a|an] <thing>
- Bot will get a random from a box.
- The box must be "prepared" first (see Bot Commands below).
- Used for user lotteries
draw
-ing without a<thing>
will always fetch an item from the default lottery/box (if its prepared). To draw from another box,<thing>
must be supplied.- Bot keeps tracks of people who have already participated in the draw.
- Trying to draw again will make the bot remind you of your previous results.
- WARNING: Records are not persisted between bot restarts!
All bot commands must be prefixed by /bot
, as in /bot <command>
.
These are commands that can only be executed by admins, based on the default
configuration in config.commands_admin
.
users
- Bot lists all users in current conversation.
- List will contain user G+ profile link and email (if available).
user <string name>
- Bot searches for users whose names contain
<string name>
in internal user list. - Spaces are not allowed.
- The bot will search all users in all participating conversations.
hangouts
- Bot lists all participating conversations with additional details.
- Legend:
c
= commands enabled;f
= forwarding enabled;a
= auto-replies.
rename <string title>
- Bot renames the current conversation.
- Spaces in the title are allowed.
- Works with both 1-on-1 or group conversations.
- Note: 1-on-1 renames may not reflect their title properly on desktop clients.
leave [<conversation id>]
- Bot leaves the current hangout if
<conversation id>
not specified.
easteregg <ponies|pitchforks|bikeshed|shydino> <number> <period>
- Bot activates Hangouts easter-egg animation (varies by client).
<number>
is the amount of repetition with delay of<period>
in seconds.
quit
- Kills the running bot process on the server with a disconnection.
config get <key> [<subkey> [...]]
- Bot reads config.json and displays contents of
config.<key>[.<subkey>...]
config set <key> [<subkey> [...]] "<value>"
- Bot sets contents of
config.<key>[.<subkey>...]
to<value>
<value>
must be enclosed in double-quotes and is interpreted as JSON.- Changes are saved instantly into
config.json
. - WARNING: This command is low-level and can scramble the configuration.
config append <key> [<subkey> [...]] "<value>"
- Bot appends to list at
config.<key>[.<subkey>...]
<value>
must be enclosed in double-quotes and is interpreted as JSON.- Only works if the key pointed at is an actual list.
- Usually used to add administrator ids to
config.admins
- WARNING: This command is low-level and can scramble the configuration.
config remove <key> [<subkey> [...]] "<value>"
- Bot removes specified from list at
config.<key>[.<subkey>...]
<value>
must be enclosed in double-quotes and is interpreted as JSON.- Only works if the key pointed at is an actual list.
- Usually used to remove administrator ids from
config.admins
- WARNING: This command is low-level and can scramble the configuration.
These are commands that can be executed by any user, based on the default
configuration in config.commands_admin
.
help
- Bot lists all supported commands.
ping
- Bot replies with a
pong
.
echo <string anything>
- Bot replies with
<string anything>
as the message. - Spaces are allowed.
pushbulletapi <apikey|false|0|-1>
- Sets/unsets the pushbullet api key for current user.
- When user is @mentioned, bot will alert user through PushBullet.
- If the push fails, bot will revert to normal hangouts-based alert.
false
,0
or-1
Disables pushbullet integration for current user.
dnd
- Toggles global DND (Do Not Disturb) for current user.
- Bot will message user whether DND is toggled on or off.
- User will not receive alerts for @mentions.
setnickname <nickname>
- Bot sets the nickname for the current user
/whoami
will return the current nickname- Call it again to re-set the
<nickname>
as preferred
whoami
- Bot replies with the current user information:
- first name, nickname and
chat_id
, OR - full name and
chat_id
- first name, nickname and
whereami
- Bot replies with the conversation name and
conversation id
.
mention <name fragment> [test]
- Alias for @.
- Triggers the same mechanism for @mentions.
<name fragment>
cannot contain spaces.- Adding optional second parameter
test
will show additional log information inside the current conversation when attempting to alert users. This can be used to check for any @mention errors with specific users.
lookup <keyword>
- Used in conjunction with a published Google Spreadsheet
- Need to enable in config:
spreadsheet_enabled
,spreadsheet_url
andspreadsheet_table_class
- Will look up each row of a spreadsheet and if the keyword is found will return the whole row
prepare [<things>] <listdef>
- Bot prepares a list of
<things>
and puts them in a virtual box for lottery drawings.- If
<things>
is not supplied, then "default" will be used. - WARNING: Records are not persisted between bot restarts!
- If
<listdef>
can be:- comma-separated list of values (no spaces!) e.g.
abc,ghi,xyz
- range of numbers e.g. 50-100
- "numberTokens" e.g. 9long1short
- comma-separated list of values (no spaces!) e.g.
- Each user must issue
/me draws
(or similar) to get a random item from the box. Note:/me draw
always draws from "default" if available; to draw from another box,/me draw [a|an] <thing>
- Run the bot with the
-d
parameter e.g.python3 hangupsbot.py -d
- this lowers the log level toINFO
for a more verbose and informative log file. tail
the log file, which is probably located at/<user>/.local/share/hangupsbot/hangupsbot.log
- the location varies by distro!- Console output (STDOUT) is fairly limited whatever the log level, so rely on the output of the log file instead.
Hooks allow extension of bot functionality by adding modular packages which contain class methods. These methods are called on common chat events:
init
, called when the hook is first loaded (one-time per run)on_chat_message
on_membership_change
on_rename
A fully-functional chat logger is provided as part of the repo, and can be
found in hangoutsbot/hooks/chatlogger/writer.php
. The chat logger logs each
chat the bot is operating in inside separate text files.
Note that hooks can use config.json
as a configuration source as well. In
the case of the example chat logger, the following configuration is necessary:
...,
"hooks": [
{
"module": "hooks.chatlogger.writer.logger",
"config":
{
"storage_path": "<location to store chat log files>"
}
}
],
...
Sinks allow the bot to receive external events in the form of JSON-based web requests. Presently the bot comes pre-packaged with several sinks:
- GitLab-compatible web hook sink that post git pushes in a hangout
- GitHub-compatible web hook sink that post git pushes in a hangout
- demo implementation that works with
hangupsbot/tests/send.py
The sink/receiver is based on BaseHTTPRequestHandler
-
hangoutsbot/sinks/generic/simpledemo.py
is a very basic example.
Some recommendations:
- Always use SSL/TLS, a self-signed certificate is better than nothing
- Setting
config.jsonrpc[].name
to "127.0.0.1" will start the sink but only allow connections from localhost - use this to debug potentially unsafe sinks.
As noted previously, a GitLab-compatible sink is available for posting pushes into a hangout - these are the configuration instructions:
Important: Still under development, subject to change
-
Generate a .pem file for SSL/TLS. It can be generated anywhere accessible to the script. This is a mandatory step as the sink will refuse to start without SSL/TLS. A self-signed certificate will do:
openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
-
Open the bot's
config.json
file and modify thejsonrpc
key as follows:..., "jsonrpc": [ { "module": "sinks.gitlab.simplepush.webhookReceiver", "certfile": "<location of .pem file>", "port": 8000 } ], ...
-
(Re-)start the bot
-
Determine which group hangout you want to receive GitLab events. In that hangout, execute
/bot whereami
- the bot will message the id for that specific hangout. Record the conversation id. -
In your GitLab instance, access Project Settings > Web Hooks
-
Select which project events you want to be notified of and specify this URL:
https://<your bot ip/domain name>:8000/<conversation id>/
-
After entering the above, Add Web Hook, then test the hook.
- easier setup/configuration
- run as service (cron works too!)
- better debug output
- A functional (and running!) version of hubot. Configuring this is beyond the scope of this document. Please refer to the installation instructions on the GitHub repo.
- A functional (also running!) copy of hangupsbot.
- Both hubot and hangupsbot should run on the same server to reduce network connectivity issues
git clone
ALL THE THINGS (as usual).git submodule update --init hubot-web
to retrieve the forked copy of hubot-web that is compatible with hangupsbot.- Proceed to your hubot folder, and execute
npm install hubot-web
- this acquires the dependencies for hubot-web and installs the npm version (which we will modify shortly). - Important: Overwrite the installed version of
hubot/node_modules/hubot-web/index.coffee
withhubot-web/index.coffee
from the forked version inside the submodule. - Modify your working hangupsbot config.json and add the following sinks/hooks:
"hooks": [
{
"config": {
"HUBOT_URL": "http://127.0.0.1:8080/receive/"
},
"module": "hooks.hubotsend.post.sender"
}
]
and
"jsonrpc": [
{
"certfile": "/root/server.pem",
"module": "sinks.hubotreceive.post.receiver",
"name": "127.0.0.1",
"port": 8081
}
]
- On the console in the hubot server, use the following configuration:
export HUBOT_HTML_RESPONSE="true"
export HUBOT_REST_SEND_URL="https://127.0.0.1:8081/"
- Restart hubot with
bin/hubot --adapter web
. You will not get a shell prompt, the server will just start and become non-interactive. - Restart hangupsbot, and ensure that the new sink and hook starts properly.
Open your hangout with hangupsbot, and type a standard hubot command
e.g. hubot time
, hubot ping
. After a brief lag, you should see hubot's
responses in the hangout.
Bot for Google Hangouts
- Python >= 3.3
- hangups (https://github.com/tdryer/hangups)
- appdirs (https://github.com/ActiveState/appdirs)
- asyncio (https://pypi.python.org/pypi/asyncio) for Python < 3.4
- BeautifulSoup4
Run hangupsbot --help
to see all available options.
Start HangupsBot by running hangupsbot
.
You can configure basic settings in config.json
file. This file will be
copied to user data directory (e.g. ~/.local/share/hangupsbot/
on Linux)
after first start of HangupsBot.
The first time you start HangupsBot, you will be prompted to log into your Google account. Your credentials will only be sent to Google, and only session cookies will be stored locally. If you have trouble logging in, try logging in through a browser first.
usage: hangupsbot [-h] [-d] [--log LOG] [--cookies COOKIES] [--config CONFIG]
optional arguments:
-h, --help show this help message and exit
-d, --debug log detailed debugging messages (default: False)
--log LOG log file path (default:
~/.local/share/hangupsbot/hangupsbot.log)
--cookies COOKIES cookie storage path (default:
~/.local/share/hangupsbot/cookies.json)
--config CONFIG config storage path (default:
~/.local/share/hangupsbot/config.json)