1212api_key = "testing"
1313base_url = "http://127.0.0.1:5000/api/events/"
1414events_folder = Path ("archive" )
15- tags_file = "tags.csv "
15+ tags_file = "tags.txt "
1616tags = {}
1717error_files = []
1818error_file = "errors.txt"
@@ -92,7 +92,7 @@ def get_date_time(date_str: str, path: Path) -> datetime:
9292 return time
9393
9494
95- def parse_event (path : Path ) -> dict :
95+ def parse_event (path : Path , repeat : bool ) -> dict :
9696 """Parse an event and return it as a dictionary."""
9797
9898 with path .open ("rb" ) as f :
@@ -111,28 +111,31 @@ def parse_event(path: Path) -> dict:
111111 # add description
112112 event ["description" ] = parts [2 ].strip () if parts [2 ].strip () else event ["title" ]
113113
114- # parse start time
115- start_time = get_date_time (event ["date" ], path )
116- event ["start_time" ] = start_time
114+ if not repeat :
115+ # parse start time
116+ start_time = get_date_time (event ["date" ], path )
117+ event ["start_time" ] = start_time
117118
118- # parse end time if supplied
119- if "end_time" in event :
120- try :
121- # attempt to parse as ISO-8601 format
122- event ["end_time" ] = datetime .fromisoformat (event ["end_time" ]).astimezone (
123- pytz .timezone ("Europe/London" )
124- )
125- except ValueError :
126- # if that fails, use custom parsing
127- time , _ = parsedatetime .Calendar ().parseDT (
128- event ["end_time" ], event ["start_time" ], pytz .timezone ("Europe/London" )
129- )
130- event ["end_time" ] = time
131-
132- if event ["end_time" ] < event ["start_time" ]:
133- raise ValueError (
134- f"End ({ event ["end_time" ]} ) is before start ({ event ["start_time" ]} )"
135- )
119+ # parse end time if supplied
120+ if "end_time" in event :
121+ try :
122+ # attempt to parse as ISO-8601 format
123+ event ["end_time" ] = datetime .fromisoformat (
124+ event ["end_time" ]
125+ ).astimezone (pytz .timezone ("Europe/London" ))
126+ except ValueError :
127+ # if that fails, use custom parsing
128+ time , _ = parsedatetime .Calendar ().parseDT (
129+ event ["end_time" ],
130+ event ["start_time" ],
131+ pytz .timezone ("Europe/London" ),
132+ )
133+ event ["end_time" ] = time
134+
135+ if event ["end_time" ] < event ["start_time" ]:
136+ raise ValueError (
137+ f"End ({ event ["end_time" ]} ) is before start ({ event ["start_time" ]} )"
138+ )
136139
137140 # process icon to convert icons/<icon>.svg to <icon>
138141 if "icon" in event :
@@ -141,76 +144,94 @@ def parse_event(path: Path) -> dict:
141144 return event
142145
143146
144- def import_events () -> None : # noqa: PLR0912
147+ def add_event (file : Path , event : dict ) -> None : # noqa: PLR0912
148+ """Add an event to the API"""
149+
150+ if "tags" in event :
151+ event_tags = event .pop ("tags" )
152+ for tag in event_tags :
153+ if tag not in tags :
154+ # if tag doesn't exist, create it
155+ tags [tag ] = [str (file )]
156+ else :
157+ # otherwise, append to existing tag
158+ tags [tag ].append (str (file ))
159+
160+ # create colour and icon if not present
161+ if "colour" not in event :
162+ if "gaming" in event ["title" ].lower ():
163+ event ["colour" ] = "gaming"
164+ event ["icon" ] = "fng" if not event .get ("icon" ) else event ["icon" ]
165+ if "social" in event ["title" ].lower ():
166+ event ["colour" ] = "social"
167+ if any (word in event ["location" ].lower () for word in ["duck" , "coach" ]):
168+ event ["colour" ] = "social"
169+ event ["icon" ] = "hamburger" if not event .get ("icon" ) else event ["icon" ]
170+
171+ # prepare event and send to API
172+ event_json = {
173+ "name" : event ["title" ],
174+ "description" : event ["description" ],
175+ "location" : event ["location" ],
176+ "start_time" : event ["start_time" ].strftime ("%Y-%m-%dT%H:%M" ),
177+ }
178+ if "draft" in event :
179+ event_json ["draft" ] = event ["draft" ]
180+ if "location_url" in event :
181+ event_json ["location_url" ] = event ["location_url" ]
182+ if "icon" in event :
183+ event_json ["icon" ] = event ["icon" ]
184+ if "colour" in event :
185+ event_json ["colour" ] = event ["colour" ]
186+ if "end_time" in event :
187+ event_json ["end_time" ] = event ["end_time" ].strftime ("%Y-%m-%dT%H:%M" )
188+
189+ response = requests .post (
190+ base_url + "create/" ,
191+ json = event_json ,
192+ headers = {"Authorization" : api_key },
193+ timeout = 5 ,
194+ )
195+
196+ if response .status_code == 201 : # noqa: PLR2004
197+ print (f"Successfully imported { file } " )
198+ else :
199+ print (f"Failed to import { file } : { response .text .replace ("\n " , " " )} " )
200+ error_files .append ((file , response .text ))
201+
202+
203+ def import_events () -> None :
145204 """Import events from the archive folder and add them to the new API"""
146205
147206 print ("Importing events..." )
148207 for file in events_folder .rglob ("*.md" ):
149208 print (f"Importing { file } ..." )
150209
151210 try :
152- if "repeat" in str (file .parent ):
153- # skip for now
154- continue
155- else :
156- event = parse_event (file )
157- except Exception as e :
211+ event = parse_event (file , "repeat" in file .parts )
212+ except ValueError as e :
158213 print (f"Error parsing { file } : { e } " )
159214 error_files .append ((file , str (e )))
160215 continue
161216
162- # tags processing
163- if "tags" in event :
164- event_tags = event .pop ("tags" )
165- for tag in event_tags :
166- if tag not in tags :
167- # if tag doesnt exist, create it
168- tags [tag ] = [event ["title" ]]
169- else :
170- # otherwise, append to existing tag
171- tags [tag ].append (event ["title" ])
172-
173- # create colour
174- if "colour" not in event :
175- if "gaming" in event ["title" ].lower ():
176- event ["colour" ] = "gaming"
177- event ["icon" ] = "fng"
178- if "social" in event ["title" ].lower ():
179- event ["colour" ] = "social"
180- if any (word in event ["location" ].lower () for word in ["duck" , "coach" ]):
181- event ["colour" ] = "social"
182- event ["icon" ] = "hamburger"
183-
184- # prepare event and send to API
185- event_json = {
186- "name" : event ["title" ],
187- "description" : event ["description" ],
188- "location" : event ["location" ],
189- "start_time" : event ["start_time" ].strftime ("%Y-%m-%dT%H:%M" ),
190- }
191- if "draft" in event :
192- event_json ["draft" ] = event ["draft" ]
193- if "location_url" in event :
194- event_json ["location_url" ] = event ["location_url" ]
195- if "icon" in event :
196- event_json ["icon" ] = event ["icon" ]
197- if "colour" in event :
198- event_json ["colour" ] = event ["colour" ]
199- if "end_time" in event :
200- event_json ["end_time" ] = event ["end_time" ].strftime ("%Y-%m-%dT%H:%M" )
201-
202- response = requests .post (
203- base_url + "create/" ,
204- json = event_json ,
205- headers = {"Authorization" : api_key },
206- timeout = 5 ,
207- )
208-
209- if response .status_code == 201 : # noqa: PLR2004
210- print (f"Successfully imported { file } " )
217+ if "repeat" in file .parts :
218+ for week in event ["weeks" ]:
219+ event_copy = event .copy ()
220+ event_date = get_date_from_week (file .parts [1 ], file .parts [2 ], week )
221+ time , _ = parsedatetime .Calendar ().parseDT (
222+ event ["date" ], event_date , pytz .timezone ("Europe/London" )
223+ )
224+ event_copy ["start_time" ] = time
225+ if "end_time" in event_copy :
226+ time , _ = parsedatetime .Calendar ().parseDT (
227+ event ["end_time" ],
228+ event_copy ["start_time" ],
229+ pytz .timezone ("Europe/London" ),
230+ )
231+ event_copy ["end_time" ] = time
232+ add_event (file , event_copy )
211233 else :
212- print (f"Failed to import { file } : { response .text .replace ("\n " , " " )} " )
213- error_files .append ((file , response .text ))
234+ add_event (file , event )
214235
215236 # write tags to file
216237 with Path (tags_file ).open ("w" , encoding = "utf-8" ) as f :
0 commit comments