Skip to content

Hangouts auth instructions #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -121,7 +121,7 @@ Supported commands:
errors during every synchronization run :-)."
"``-c``, ``--color=CHOICE,`` ``--colour=CHOICE``","Specify whether ANSI escape sequences for text and background colors and
text styles are to be used or not, depending on the value of ``CHOICE``:

- The values 'always', 'true', 'yes' and '1' enable colors.
- The values 'never', 'false', 'no' and '0' disable colors.
- When the value is 'auto' (this is the default) then colors will
@@ -405,6 +405,47 @@ In the future more backends may be added:
generated ten years ago (circa 2008) because I have megabytes of such chat
logs stored in backups 🙂.


Google Hangouts Notes
---------------------
Google Hangouts has recently changed their authorization flow and it cannot easily be automated. Here are the steps to manually authorize Google Hangouts:

----

1) Install hangups (https://github.com/tdryer/hangups). I recommend using the latest git version due to the fragile nature of its reverse engineered protocol:

.. code-block:: bash

pip install 'git+https://github.com/tdryer/hangups'

----

2) To authorize hangups, you must include an oauth cookie. Run the following python script, open the link in a browser, log in to Google, open the Developer Tools (Ctrl+Shift+i in Firefox), go to the "Storage" tab, and copy the cookie labeled "oauth token". Paste this token string into the terminal prompt. Now hangups will be authorized with a token in `$HOME/.cache/hangups/refresh_token.txt`, and chat_archive will read the token from there.

.. code-block:: python

#!/usr/bin/env python3

import os, hangups, requests, appdirs

print('Open this URL:')
print(hangups.auth.OAUTH2_LOGIN_URL)

authorization_code = input('Enter oauth_code cookie value: ')

with requests.Session() as session:
session.headers = {'user-agent': hangups.auth.USER_AGENT}
access_token, refresh_token = hangups.auth._auth_with_code(
session, authorization_code
)

dirs = appdirs.AppDirs('hangups', 'hangups')
token_path = os.path.join(dirs.user_cache_dir, 'refresh_token.txt')
hangups.auth.RefreshTokenCache(token_path).set(refresh_token)

----


History
-------

7 changes: 6 additions & 1 deletion chat_archive/backends/hangouts.py
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import html
import os
import time
import appdirs

# External dependencies.
import hangups
@@ -70,6 +71,10 @@ def client(self):
"""The hangups client object."""
# Make sure the directory with cached credentials exists.
ensure_directory_exists(os.path.dirname(self.cookie_file))

dirs = appdirs.AppDirs('hangups', 'hangups')
token_path = os.path.join(dirs.user_cache_dir, 'refresh_token.txt')

return Client(
get_auth(
GoogleAccountCredentials(
@@ -81,7 +86,7 @@ def client(self):
description="Google account password",
),
),
RefreshTokenCache(self.cookie_file),
RefreshTokenCache(token_path)
)
)

5 changes: 4 additions & 1 deletion chat_archive/backends/slack.py
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
import datetime
import decimal
import html
import time

# External dependencies.
from humanfriendly import Spinner
@@ -135,10 +136,12 @@ def import_messages(self, source, conversation_in_db):
external_id=message["ts"],
html=html,
raw=message["text"],
sender=self.get_or_create_contact(external_id=message["user"]),
sender=self.get_or_create_contact(external_id=message.get("user")),
text=html_to_text(html),
timestamp=datetime.datetime.utcfromtimestamp(float(message["ts"])),
)

time.sleep(0.01)
if not conversation_in_db.import_complete:
conversation_in_db.import_complete = True

4 changes: 3 additions & 1 deletion chat_archive/backends/telegram.py
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
# Standard library modules.
import asyncio
import os
import pytz

# External dependencies.
from property_manager import lazy_property, mutable_property, required_property
@@ -121,7 +122,8 @@ async def connect_then_sync(self):
)
if not conversation_in_db.import_complete:
await self.perform_initial_sync(dialog, conversation_in_db)
elif dialog.date > conversation_in_db.last_modified:

elif dialog.date > conversation_in_db.last_modified.replace(tzinfo=pytz.utc):
logger.info("Conversation was updated (%s) ..", dialog.id)
await self.update_conversation(dialog, conversation_in_db)
conversation_in_db.last_modified = dialog.date