From b22b408d0409247019479499915060c2bdb40d86 Mon Sep 17 00:00:00 2001 From: Dan Hallock Date: Sun, 4 Oct 2015 13:28:20 -0700 Subject: [PATCH 1/2] Fix asset path Append sys.path[0] to the assets paths so that the copy will succeed even if the current working directory is not the script directory. --- html-transcript.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/html-transcript.py b/html-transcript.py index 6bf3df6..8dc6e66 100644 --- a/html-transcript.py +++ b/html-transcript.py @@ -122,8 +122,8 @@ def write_html_transcript(messages, outfile, imgcache): def write_html(folder, messages, emoji=True): imgcache = ImageCache(folder) index_fn = os.path.join(folder, 'index.html') - shutil.copyfile('assets/groupme.css', os.path.join(folder, 'groupme.css')) - shutil.copyfile('assets/groupme.js', os.path.join(folder, 'groupme.js')) + shutil.copyfile(sys.path[0] + '/assets/groupme.css', os.path.join(folder, 'groupme.css')) + shutil.copyfile(sys.path[0] + '/assets/groupme.js', os.path.join(folder, 'groupme.js')) with open(index_fn, 'w') as f: f.write(_HTML_HEADER) write_html_transcript(messages, f, imgcache) From b960d8d6b0757027c50342b7e1eadec4a3beee6d Mon Sep 17 00:00:00 2001 From: Dan Hallock Date: Sun, 4 Oct 2015 13:56:07 -0700 Subject: [PATCH 2/2] Direct message support Add support for direct messages in addition to group chats. Added a new --mode command line switch, defaults to group. --- README.md | 4 ++-- groupme-fetch.py | 13 +++++++++---- html-transcript.py | 12 ++++++++++-- simple-transcript.py | 10 ++++++---- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2572d51..b05dc2f 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,13 @@ The files in the `stat` folder are self-explanatory; they allow for learning int Log into [GroupMe's web interface](https://web.groupme.com/groups) and use Chrome or Safari's inspector to monitor the network requests when you load one of your groups. -You'll notice a GET request to an endpoint `https://v2.groupme.com/groups/GROUP_ID/messages`. +You'll notice a GET request to an endpoint `https://v2.groupme.com/groups/GROUP_ID/messages` for a group chat, or `https://api.groupme.com/v3/direct_messages?other_user_id=OTHER_USER_ID` for direct messages. One of the headers sent with that request, `X-Access-Token`, is your access token. ## Finding your group ID -Again, in GroupMe's web interface, the group ID is the numeric ID included in the group's URL (`https://web.groupme.com/groups/GROUP_ID`). +Again, in GroupMe's web interface, the group ID is the numeric ID included in the group's URL (`https://web.groupme.com/groups/GROUP_ID`). For direct messages, you'll need the other_user_id. ## Requirements/Dependencies/Python diff --git a/groupme-fetch.py b/groupme-fetch.py index f67c38a..1efedee 100644 --- a/groupme-fetch.py +++ b/groupme-fetch.py @@ -34,7 +34,7 @@ def main(): specific message IDs """ parser = argparse.ArgumentParser() - parser.add_argument('group') + parser.add_argument('group', help="The group id (for group chats) or other_user_id (for direct messages) from your GroupMe Web session") parser.add_argument('accessToken') parser.add_argument("--resumePrevious", action='store_true', default=False, help="Resume based on the last found files and get previous messages.") parser.add_argument("--resumeNext", action='store_true', default=False, help="Resume based on the last found files and get next messages.") @@ -42,6 +42,7 @@ def main(): parser.add_argument("--newest", help="The ID of the newest (bottom-most) message in the existing transcript file") parser.add_argument("--pages", type=int, help="The number of pages to pull down (defaults to as many as the conversation has") + parser.add_argument("--mode", default="group", help="Type of chat to download: 'group' or 'direct_messages'. Defaults to group.") args = parser.parse_args() @@ -50,6 +51,7 @@ def main(): beforeId = args.oldest stopId = args.newest pages = args.pages + mode = args.mode transcriptFileName = 'transcript-{0}.json'.format(group) transcript = loadTranscript(transcriptFileName) @@ -64,7 +66,7 @@ def main(): else: stopId = transcript[-1]['id'] - transcript = populateTranscript(group, accessToken, transcript, beforeId, stopId, pages) + transcript = populateTranscript(group, accessToken, transcript, beforeId, stopId, mode, pages) # sort transcript in chronological order transcript = sorted(transcript, key=lambda k: k[u'created_at']) @@ -120,10 +122,13 @@ def loadTempTranscript(tempFileName): return [] -def populateTranscript(group, accessToken, transcript, beforeId, stopId, pageLimit=None): +def populateTranscript(group, accessToken, transcript, beforeId, stopId, mode, pageLimit=None): complete = False pageCount = 0 - endpoint = 'https://v2.groupme.com/groups/' + group + '/messages' + if mode == 'direct_messages': + endpoint = 'https://api.groupme.com/v3/direct_messages?other_user_id=' + group + else: + endpoint = 'https://v2.groupme.com/groups/' + group + '/messages' headers = { 'Accept': 'application/json, text/javascript', 'Accept-Charset': 'ISO-8859-1,utf-8', diff --git a/html-transcript.py b/html-transcript.py index 8dc6e66..7a0535d 100644 --- a/html-transcript.py +++ b/html-transcript.py @@ -79,10 +79,18 @@ def write_html_transcript(messages, outfile, imgcache): text = message[u'text'] if text is None: text = u'' - system = message[u'system'] + system = message.get(u'system', None) faves = message[u'favorited_by'] nlikes = faves if faves == 0 else len(faves) - pic = message[u'picture_url'] + pic = message.get(u'picture_url', None) + + # Picture is included as an attachment on direct messages. + # This might have to be rewritten if there are ever multiple images + # attached to a single message. Right now I've only seen multiple + # attachments for emoji. + if message.get(u'attachments', []) != []: + if message[u'attachments'][0].get(u'type', None) in ['image', 'linked_image']: + pic = message[u'attachments'][0][u'url'] # Open div diff --git a/simple-transcript.py b/simple-transcript.py index 982a1f8..0f96c07 100644 --- a/simple-transcript.py +++ b/simple-transcript.py @@ -21,7 +21,7 @@ def printTranscript(messages, outputFilename): else: text = "(no text)" - if message[u'system'] is True: + if message.get(u'system', None) is True: system_padded = '(SYS) ' else: system_padded = '' @@ -31,10 +31,12 @@ def printTranscript(messages, outputFilename): else: favorites_padded = '' - if message[u'picture_url'] is not None: + pic = '' + if message.get(u'picture_url') is not None: pic = ' ; photo URL ' + message[u'picture_url'] - else: - pic = '' + elif message.get(u'attachments', []) != []: + if message[u'attachments'][0].get(u'type', None) in ['image', 'linked_image']: + pic = ' ; photo URL ' + message[u'attachments'][0][u'url'] line = u'{0}{1}({2}){3}: {4}{5}\n'.format( system_padded, name, time, favorites_padded, text, pic