Skip to content

Instantly share code, notes, and snippets.

@coderunner007
Last active December 2, 2023 20:24
Show Gist options
  • Save coderunner007/2011ac341c6910d30eeb19c70915c41c to your computer and use it in GitHub Desktop.
Save coderunner007/2011ac341c6910d30eeb19c70915c41c to your computer and use it in GitHub Desktop.
Convert Journey journal backup to Obsidian markdown files. Journey: https://journey.cloud/app/ , Obsidian: https://obsidian.md/
import os
import json
import time
import shutil
# Change the variables here according to what is present in your filesystem
journey_input_folder = os.path.join(os.environ['HOME'],"Documents","Journey","journey-<hash>")
obsidian_output_folder = os.path.join(os.environ['HOME'],"Documents","Journey","FromJourney")
obsidian_attachments_folder = os.path.join(os.environ['HOME'],"Documents","Journey", "FromJourney", "attachments")
# To convert from Daily Note to python's date format, check this gist out: https://gist.github.com/asafge/0b13c5066d06ae9a4446
obsidian_daily_note_date_format = "%Y %B %d %a"
class JourneyData:
jsonToAttributes = {
"text": ["text", ""],
"epochTime": ["date_journal", ""],
'tags': ["tags", []],
'photoIDs': ["photos", []],
}
def __init__(self, journeyJSONData):
self.__initialize_main_data(journeyJSONData)
self.extra_data = self.__filter_other_data(journeyJSONData)
def to_formatted_date(self, date_format):
return time.strftime(date_format,
time.localtime(convertMillisecondsToSeconds(self.epochTime)))
def __initialize_main_data(self, journeyJSONData):
for key, value in JourneyData.jsonToAttributes.items():
self.__setattr__(key, journeyJSONData.get(value[0], value[1]))
def __filter_other_data(self, journeyJSONData):
return { key: journeyJSONData.get(key, "") for key in
filter(lambda x:x not in map(lambda x: x[0],
JourneyData.jsonToAttributes.values()), journeyJSONData.keys())}
def __str__(self):
return "<>".join(["|".join(self.to_tags()), self.text[1:10],
self.to_formatted_date(obsidian_daily_note_date_format),
"|".join(self.extra_data.keys()),
"|".join(self.to_image_markdown())])
class AggregatedJourneyData:
def __init__(self, journey_data):
self.text = journey_data.text
self.photoIDs = journey_data.photoIDs
self.tags = journey_data.tags
self.formatted_date = journey_data.to_formatted_date(obsidian_daily_note_date_format)
self.extra_data = journey_data.extra_data
def combine(self, another_journey_data):
self.text = self.__combine_text(another_journey_data)
self.photoIDs = self.__combine_images(another_journey_data)
self.tags = self.__combine_tags(another_journey_data)
def __combine_text(self, another_journey_data):
return f'''{self.text}
---
{another_journey_data.text}
'''
def __combine_tags(self, another_journey_data):
return list(set(self.tags + another_journey_data.tags))
def __combine_images(self, another_journey_data):
return self.photoIDs + another_journey_data.photoIDs
def to_image_markdown(self):
return "\n".join([ f'![[{photoID}]]' for photoID in self.photoIDs ])
def to_tags(self):
return " ".join([ f'[[{tag}]]' for tag in self.tags])
def to_other_data(self):
return "\n".join([f'{key}:{value}' for key, value in
self.extra_data.items()])
def to_file_content(self):
return f'''#fromJourney
{self.text}
### Images
{self.to_image_markdown()}
### Other Data
{self.to_other_data()}
### Tags
{self.to_tags()}
'''
def createObsidianFile(journeyData, new_file_path):
obsidian_file_extension = "md"
with open(os.path.join(new_file_path,
".".join([journeyData.formatted_date, obsidian_file_extension])),
"w") as f:
f.write(journeyData.to_file_content())
def convertMillisecondsToSeconds(ms):
return ms // 1000
def getDateInObsidianDailyNoteFormat(epochDateStr):
return epochDateStr
def getAllJSONFiles(path):
return [ os.path.join(path, x) for x in os.listdir(path) if x.endswith("json") ]
def getAllNonJSONFiles(path):
return [ os.path.join(path, x) for x in os.listdir(path) if not x.endswith("json") ]
def getJourneyData(file):
with open (file, "r") as f:
return JourneyData(json.load(f))
def aggregate(all_journey_data):
aggregate_output = {}
for journey_entry in all_journey_data:
key = journey_entry.to_formatted_date(obsidian_daily_note_date_format)
if key in aggregate_output:
aggregate_output[key].combine(journey_entry)
else:
aggregate_output[key] = AggregatedJourneyData(journey_entry)
return aggregate_output.values()
def createAllData(folder_path):
return [getJourneyData(file) for file in getAllJSONFiles(folder_path)]
def createObsidianFilesFromJourney(input_folder, output_folder):
for data in aggregate(createAllData(input_folder)):
createObsidianFile(data, output_folder)
def copyObsidianAttachmentsFromJourney(input_folder, output_folder):
for attachment_path in getAllNonJSONFiles(input_folder):
shutil.copy2(attachment_path, os.path.join(output_folder,
os.path.basename(attachment_path)))
if __name__ == '__main__':
createObsidianFilesFromJourney(journey_input_folder, obsidian_output_folder)
copyObsidianAttachmentsFromJourney(journey_input_folder,
obsidian_attachments_folder)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment