Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions tools/events/maybe-rust-meetups.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"https://www.meetup.com/hackerdojo/events/",
"https://www.meetup.com/hackschool-rhein-neckar/events/",
"https://www.meetup.com/houston-functional-programming-users-group/events/",
"https://www.meetup.com/jersey-city-classy-curious-coders-club-cooperative/events/",
"https://www.meetup.com/pydelhi/events/",
"https://www.meetup.com/stacja-it-krakow/events/",
"https://www.meetup.com/stacja-it-trojmiasto/events/",
Expand Down
89 changes: 89 additions & 0 deletions tools/events/meetup-automation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Event Sink
The maintainer of the Events section is faced with manual work; this process automates generation of a draft events list using various Event Source Modules that gather event information, and an Event Sink that sorts, groups and formats the events into a pre-determined markdown format.

## Getting Started:
### Pre-Requisites:
- Event sink requires Python3 installation.
- For specific module requirements: `pip install -r requirements.txt`
- See https://geopy.readthedocs.io/en/stable/# for `geopy` module documentation.

### Setup the virutal environment:

```bash
python3 -m venv events-venv && source events-venv/bin/activate
pip install -r requirements.txt
```

### Setup your environment variables:

```bash
export MEETUP_PRIVATE_KEY="<path to local RSA OAuth pem private key>"
# e.g. export MEETUP_PRIVATE_KEY="$HOME/.ssh/meetup_signing_key.pem"
export MEETUP_AUTHORIZED_MEMBER_ID="<ID of the member who created Meetup OAuth client>"
export MEETUP_CLIENT_KEY="<OAuth token ID>"
```

### Running:
Before running please check that all Event Source module function calls are included in `event_list` (function calls should concatenate into a single list of event objects).

To run this code:

```py
python3 main.py -g <location of meetups JSON input list>
# e.g. python3 main.py -g ../events/meetups.json
```

### How to Add a New Event Source Module:
- To write a new event source module, it must be written in python. Event sources should be a function that passes no parameters and returns a list of events with required variables detailed above. If the event source has additional requirements, that should be added to `requirements.txt`. The event source should detail any specific run instructions in it's own documentation. Look at `test_events.py` for bare-minimum event list output.
- To run a new event source, import the new module from new event source and add the function call to `event_list`.

## Architecture:
### Event Class:
**Required Variables**
- `name` (string): Title of the event.
- `location` (string): Location of the event either in full detail (e.g. `"111 test st, city, country, postcode"`) to be formatted by `geopy` module and `format_location()` in event sink, or in `"city, state/territory, country"` format with state/territory details included if the location is in Australia, Canada or United States. See code sample included below for an example of location formatting.
- Note: If location string is in `"city, state, country"` format, for both state/territory and country ISO alpha-2 codes must be used (e.g. AU for Australia, CA for California).
- `date` (date or datetime): Date of event in the locations local time (NOT the local time of where the program is being run).
- `url` (string): Unique URL for event page details.
- `virtual` (boolean): If event is online.
- `organizerName` (string): Name of event organiser.
- `organizerUrl` (string): URL for event organiser webpage.

**Additional Variable(s) for Internal Use:**
- `duplicate` (boolean): Flag for potential event duplicate based on evaluation during event sink.

**Code Sample for Creating an Event:**
```py
Event(name="Test Event", location="Melbourne, VIC, AU", date=date.today(), url="website3.com", virtual=True, organizerName="Test Organizer", organizerUrl="testorg.com")
```

### Within Scope of Event Sink:
- The event sink will take a list of event objects (see `test_events.py` for example data), format the date and location data (if not done already), filter out events that are outside of the pre-determined 'date window' for the current TWiR issue then sort the events by date and then location alphabetically. After this process the list is then split via virtual or continent, and any potential duplicate events within the list are flagged (through comparison of event data). Finally, the event sink will output the details of the finalised list of events in a pre-determined markdown format, complete with virtual/continent headers.
- Note that potential duplicate events will be flagged with a `** NOTE POTENTIAL DUPLICATE: **` warning immediately preceding the event information.


### Out of Scope:
- The purpose of the event sink is to cross-reference and curate data from various sources. It shouldn't be responsible for gathering or adding required fields of data into the Event class. Any edge cases should be managed by the event sources.

### Expected Output:
Example Output from `test_events.py` data:
```
### Virtual:

* 2024-04-12 | Virtual (Dublin, IE) | [Test Organizer](testorg.com)
*[**Test Event 1**](website1.com)

### North America:

* 2024-04-03 | New York, NY, US | [Test Organizer](testorg.com)
*[**Test Event 7**](website7.com)
* 2024-04-04 | San Francisco, CA, US | [Test Organizer](testorg.com)
*[**Test Event 6**](website6.com)
* 2024-04-18 | Indianapolis, IN, US | [Test Organizer](testorg.com)
*[**Test Event 2**](website2.com)

### Oceania:

* 2024-04-04 | Sydney, NSW, AU | [Test Organizer](testorg.com)
*[**Test Event 4**](website4.com)
```
256 changes: 256 additions & 0 deletions tools/events/meetup-automation/country_code_to_continent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
# Takes an ISO alpha-2 country code and returns the continent.
# Mapping of ISO alpha-2 Country Codes to Continent, from Wikipedia.

COUNTRY_CODE_TO_CONTINENT = {
'AB': 'Asia',
'AD': 'Europe',
'AE': 'Asia',
'AF': 'Asia',
'AG': 'North America',
'AI': 'North America',
'AL': 'Europe',
'AM': 'Asia',
'AO': 'Africa',
'AR': 'South America',
'AS': 'Oceania',
'AT': 'Europe',
'AU': 'Oceania',
'AW': 'North America',
'AX': 'Europe',
'AZ': 'Asia',
'BA': 'Europe',
'BB': 'North America',
'BD': 'Asia',
'BE': 'Europe',
'BF': 'Africa',
'BG': 'Europe',
'BH': 'Asia',
'BI': 'Africa',
'BJ': 'Africa',
'BL': 'North America',
'BM': 'North America',
'BN': 'Asia',
'BO': 'South America',
'BQ': 'North America',
'BR': 'South America',
'BS': 'North America',
'BT': 'Asia',
'BV': 'Antarctica',
'BW': 'Africa',
'BY': 'Europe',
'BZ': 'North America',
'CA': 'North America',
'CC': 'Asia',
'CD': 'Africa',
'CF': 'Africa',
'CG': 'Africa',
'CH': 'Europe',
'CI': 'Africa',
'CK': 'Oceania',
'CL': 'South America',
'CM': 'Africa',
'CN': 'Asia',
'CO': 'South America',
'CR': 'North America',
'CU': 'North America',
'CV': 'Africa',
'CW': 'North America',
'CX': 'Asia',
'CY': 'Asia',
'CZ': 'Europe',
'DE': 'Europe',
'DJ': 'Africa',
'DK': 'Europe',
'DM': 'North America',
'DO': 'North America',
'DZ': 'Africa',
'EC': 'South America',
'EE': 'Europe',
'EG': 'Africa',
'ER': 'Africa',
'ES': 'Europe',
'ET': 'Africa',
'FI': 'Europe',
'FJ': 'Oceania',
'FK': 'South America',
'FM': 'Oceania',
'FO': 'Europe',
'FR': 'Europe',
'GA': 'Africa',
'GB': 'Europe',
'GD': 'North America',
'GE': 'Asia',
'GF': 'South America',
'GG': 'Europe',
'GH': 'Africa',
'GI': 'Europe',
'GL': 'North America',
'GM': 'Africa',
'GN': 'Africa',
'GP': 'North America',
'GQ': 'Africa',
'GR': 'Europe',
'GS': 'South America',
'GT': 'North America',
'GU': 'Oceania',
'GW': 'Africa',
'GY': 'South America',
'HK': 'Asia',
'HM': 'Antarctica',
'HN': 'North America',
'HR': 'Europe',
'HT': 'North America',
'HU': 'Europe',
'ID': 'Asia',
'IE': 'Europe',
'IL': 'Asia',
'IM': 'Europe',
'IN': 'Asia',
'IO': 'Asia',
'IQ': 'Asia',
'IR': 'Asia',
'IS': 'Europe',
'IT': 'Europe',
'JE': 'Europe',
'JM': 'North America',
'JO': 'Asia',
'JP': 'Asia',
'KE': 'Africa',
'KG': 'Asia',
'KH': 'Asia',
'KI': 'Oceania',
'KM': 'Africa',
'KN': 'North America',
'KP': 'Asia',
'KR': 'Asia',
'KW': 'Asia',
'KY': 'North America',
'KZ': 'Asia',
'LA': 'Asia',
'LB': 'Asia',
'LC': 'North America',
'LI': 'Europe',
'LK': 'Asia',
'LR': 'Africa',
'LS': 'Africa',
'LT': 'Europe',
'LU': 'Europe',
'LV': 'Europe',
'LY': 'Africa',
'MA': 'Africa',
'MC': 'Europe',
'MD': 'Europe',
'ME': 'Europe',
'MF': 'North America',
'MG': 'Africa',
'MH': 'Oceania',
'MK': 'Europe',
'ML': 'Africa',
'MM': 'Asia',
'MN': 'Asia',
'MO': 'Asia',
'MP': 'Oceania',
'MQ': 'North America',
'MR': 'Africa',
'MS': 'North America',
'MT': 'Europe',
'MU': 'Africa',
'MV': 'Asia',
'MW': 'Africa',
'MX': 'North America',
'MY': 'Asia',
'MZ': 'Africa',
'NA': 'Africa',
'NC': 'Oceania',
'NE': 'Africa',
'NF': 'Oceania',
'NG': 'Africa',
'NI': 'North America',
'NL': 'Europe',
'NO': 'Europe',
'NP': 'Asia',
'NR': 'Oceania',
'NU': 'Oceania',
'NZ': 'Oceania',
'OM': 'Asia',
'OS': 'Asia',
'PA': 'North America',
'PE': 'South America',
'PF': 'Oceania',
'PG': 'Oceania',
'PH': 'Asia',
'PK': 'Asia',
'PL': 'Europe',
'PM': 'North America',
'PR': 'North America',
'PS': 'Asia',
'PT': 'Europe',
'PW': 'Oceania',
'PY': 'South America',
'QA': 'Asia',
'RE': 'Africa',
'RO': 'Europe',
'RS': 'Europe',
'RU': 'Europe',
'RW': 'Africa',
'SA': 'Asia',
'SB': 'Oceania',
'SC': 'Africa',
'SD': 'Africa',
'SE': 'Europe',
'SG': 'Asia',
'SH': 'Africa',
'SI': 'Europe',
'SJ': 'Europe',
'SK': 'Europe',
'SL': 'Africa',
'SM': 'Europe',
'SN': 'Africa',
'SO': 'Africa',
'SR': 'South America',
'SS': 'Africa',
'ST': 'Africa',
'SV': 'North America',
'SY': 'Asia',
'SZ': 'Africa',
'TC': 'North America',
'TD': 'Africa',
'TG': 'Africa',
'TH': 'Asia',
'TJ': 'Asia',
'TK': 'Oceania',
'TM': 'Asia',
'TN': 'Africa',
'TO': 'Oceania',
'TP': 'Asia',
'TR': 'Asia',
'TT': 'North America',
'TV': 'Oceania',
'TW': 'Asia',
'TZ': 'Africa',
'UA': 'Europe',
'UG': 'Africa',
'US': 'North America',
'UY': 'South America',
'UZ': 'Asia',
'VC': 'North America',
'VE': 'South America',
'VG': 'North America',
'VI': 'North America',
'VN': 'Asia',
'VU': 'Oceania',
'WF': 'Oceania',
'WS': 'Oceania',
'XK': 'Europe',
'YE': 'Asia',
'YT': 'Africa',
'ZA': 'Africa',
'ZM': 'Africa',
'ZW': 'Africa',
}


def country_code_to_continent(country_code: str):
# Returns the continent a country code belongs to.
return COUNTRY_CODE_TO_CONTINENT[country_code.upper()]

Loading