Last active
December 2, 2023 20:24
-
-
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/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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