{"id":33185721,"url":"https://github.com/pafoster/gdir","last_synced_at":"2025-11-22T04:01:37.083Z","repository":{"id":57433314,"uuid":"394083423","full_name":"pafoster/gdir","owner":"pafoster","description":"Get train/bus directions using the command line","archived":false,"fork":false,"pushed_at":"2022-12-19T18:27:35.000Z","size":55,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-31T07:39:13.873Z","etag":null,"topics":["command-line","command-line-tool","python","travel"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pafoster.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-08T22:45:43.000Z","updated_at":"2024-12-21T09:49:08.000Z","dependencies_parsed_at":"2023-01-29T22:25:11.626Z","dependency_job_id":null,"html_url":"https://github.com/pafoster/gdir","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/pafoster/gdir","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pafoster%2Fgdir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pafoster%2Fgdir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pafoster%2Fgdir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pafoster%2Fgdir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pafoster","download_url":"https://codeload.github.com/pafoster/gdir/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pafoster%2Fgdir/sbom","scorecard":{"id":717731,"data":{"date":"2025-08-11","repo":{"name":"github.com/pafoster/gdir","commit":"128e5e9ab933be4d856917df5725cb5d37db8762"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-22T10:14:41.011Z","repository_id":57433314,"created_at":"2025-08-22T10:14:41.012Z","updated_at":"2025-08-22T10:14:41.012Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285731803,"owners_count":27222214,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-22T02:00:05.934Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-line","command-line-tool","python","travel"],"created_at":"2025-11-16T05:00:20.099Z","updated_at":"2025-11-22T04:01:37.078Z","avatar_url":"https://github.com/pafoster.png","language":"Python","funding_links":[],"categories":["\u003ca name=\"productivity\"\u003e\u003c/a\u003eProductivity"],"sub_categories":[],"readme":"gdir: Get Train/Bus Directions Using the Command Line\n-----------------------------------------------------\n\n``gdir`` is a command line tool which queries Google Directions. The tool displays results as human-readable text.\n\n|\n\n.. figure:: https://github.com/pafoster/gdir/raw/main/img/gdir.gif\n   :width: 576\n   :alt: Gdir in Action\n\nInstallation\n-------------------------\n``gdir`` is listed on the `Python Package Index \u003chttps://pypi.org\u003e`_ and may be installed using ``pip`` as follows:\n\n.. code:: shell-session\n\n    $ python -m pip install gdir\n\nConfiguration\n-------------------------\nYou will need a Google Directions API key. See `Google Directions API documentation \u003chttps://developers.google.com/maps/documentation/directions/get-api-key\u003e`_ for instructions on how to obtain a key.\n\nSet the shell environment variable GOOGLE_MAPS_API_KEY to your API key. This typically involves adding something like the following to your ``.profile`` file:\n\n.. code:: bash\n\n    export GOOGLE_MAPS_API_KEY=\"XXXXXXXXXXXXXXXX-XXXXXXXXXXXXX-XXXXXXXX\"\n\n**Note**: If you don't want to set up your own API key, there is a **web-based version of gdir** - try viewing https://gdir.telae.net in a terminal-based browser like `links \u003chttp://links.twibright.com/\u003e`_, `lynx \u003chttps://lynx.invisible-island.net/\u003e`_, or `w3m \u003chttps://github.com/tats/w3m\u003e`_! The web-based version (repo `also available on GitHub \u003chttps://github.com/pafoster/gdir.telae.net\u003e`_) implements most of the features described below.\n\nExample Usage\n-------------------------\nDisplay directions from **Tower Bridge, London** to **Buckingham Palace**, using any mode of public transport and departing now:\n\n.. code:: shell-session\n\n    $ gdir \"Tower Bridge, London\" \"Buckingham Place\"\n\n    08:02-08:30 (U) Tower Bridge, Tower Bridge Rd, London SE1 2UP, UK -\u003e London SW1A\n                1AA, UK 6.1km\n          7mins Walk to Tower Hill 0.5km\n    08:10-08:21 TOWER HILL board Circle underground towards Edgware Road alight at\n                ST. JAMES'S PARK\n         10mins Walk to London SW1A 1AA, UK 0.8km\n\nDisplay directions for the same origin and destination, but prefer to travel by **bus** and **depart** at **10:00am today**:\n\n.. code:: shell-session\n\n    $ gdir -b -d 10:00 \"Tower Bridge, London\" \"Buckingham Place\"\n\n    10:00-10:38 (BB) Tower Bridge, Tower Bridge Rd, London SE1 2UP, UK -\u003e London\n                SW1A 1AA, UK 7.0km\n          4mins Walk to Boss Street (Stop T) 0.3km\n    10:03-10:18 BOSS STREET (STOP T) board 381 bus towards Waterloo alight at COUNTY\n                HALL (STOP G)\n          3mins Walk to Westminster Cathedral / Victoria Station (Stop M) 0.2km\n    10:29-10:30 WESTMINSTER CATHEDRAL / VICTORIA STATION (STOP M) board 11 bus\n                towards Walham Green alight at VICTORIA STATION (STOP G)\n         10mins Walk to London SW1A 1AA, UK 0.8km\n\nDisplay **multiple options** for travelling from **London** to **Edinburgh**, **arriving** by **2pm tomorrow**:\n\n.. code:: shell-session\n\n    $ gdir -M -a 14:00+1 \"London\" \"Edinburgh\"\n\n    09:00-13:20 (T) London, UK -\u003e Edinburgh, UK 632km\n    09:00-13:20 KING'S CROSS board Lner train towards Edinburgh alight at EDINBURGH\n                WAVERLEY\n    \n    08:30-13:12 (T) London, UK -\u003e Edinburgh, UK 632km\n    08:30-13:12 KING'S CROSS board Lner train towards Edinburgh alight at EDINBURGH\n                WAVERLEY\n    \n    08:10-13:29 (TT) London, UK -\u003e Edinburgh, UK 644km\n    08:10-11:50 LONDON EUSTON board Avanti West Coast train towards Glasgow Central\n                alight at CARLISLE\n    12:07-13:29 CARLISLE board Transpennine Express train towards Edinburgh alight\n                at EDINBURGH WAVERLEY\n    \n    08:00-12:20 (T) London, UK -\u003e Edinburgh, UK 632km\n    08:00-12:20 KING'S CROSS board Lner train towards Edinburgh alight at EDINBURGH\n                WAVERLEY\n\nDisplay **walking sub-steps** for travelling from **The National Gallery, London** to **Kew Gardens, London**, using any mode of public transport and departing at **2pm** on **15th September this year**:\n\n.. code:: shell-session\n\n    $ gdir -S -d 091514:00 \"The National Gallery, London\" \"Kew Gardens, London\"\n\n    14:05-15:11 (UT) Trafalgar Square, London WC2N 5DN, UK -\u003e Royal Botanic Gardens,\n                Kew, Richmond TW9, UK 18.3km\n          3mins Walk to Charing Cross Station 0.2km\n              1 Walk southTake the stairs 69m\n              2 Turn right towards Trafalgar Square/A4 24m\n              3 Turn left towards Trafalgar Square/A4 48m\n              4 Turn right onto Trafalgar Square/A4Destination will be on the left\n                4m\n              5 Take entrance  29m\n    14:08-14:10 CHARING CROSS STATION board Bakerloo underground towards Elephant \u0026\n                Castle alight at WATERLOO\n          4mins Walk to Waterloo Station 0.2km\n              1 Take exit  60m\n              2 Take entrance London Waterloo Rail Station 0.1km\n    14:20-14:36 WATERLOO STATION board South Western Railway train towards Reading\n                alight at RICHMOND\n         15mins Walk to Royal Botanic Gardens, Kew, Richmond TW9, UK 1.1km\n              1 Take exit Richmond Rail Station 38m\n              2 Walk north-east on Kew Rd/A307 towards Sun AlleyGo through 1\n                roundabout 1.1km\n              3 Turn left 38m\n              4 Turn rightDestination will be on the left 11m\n\n**Note**: If you get a *no directions found* error, try appending the city to your origin/destination address. See also the ``-R`` flag below for setting region bias.\n\n**Note 2**: See ``-c`` ``-k`` ``-f`` flags below for setting other transport modes if required (driving, cycling, walking).\n\nDetailed Help and List of Command Line Arguments\n------------------------------------------------\n.. code::\n\n    usage: gdir [-h] [-b] [-r] [-n] [-m] [-u] [-c | -k | -f]\n                [-d time_arg | -a time_arg] [-S] [-M] [-N] [-R region_code] [-C]\n                origin destination\n    \n    Query the Google Directions API and write results to the standard output in\n    human-readable format. Uses public transport ('transit') mode by default.\n    Requires environment variable GOOGLE_MAPS_API_KEY defining a valid API key.\n    Language of directions is determined from locale configuration using\n    locale.getdefaultlocale(), which reads from LC_ALL, LC_CTYPE, LANG and\n    LANGUAGE in descending order of priority. Word wrapping is achieved using\n    shutil.get_terminal_size(), which reads from COLUMNS and which may\n    alternatively use system calls to determine the terminal width, using a fall-\n    back value of 80 if the terminal width could not be determined. Scripts may\n    use the -N flag (see below) to disable word wrapping but should not make\n    excessive assumptions about the structure of output: When using the -N flag,\n    valid assumptions are 1) routes are delimited by empty lines 2) each route may\n    be represented as a two-column table, where rows are separated by newlines and\n    where the first and second column in the table are separated by a single space\n    3) values in the first column may be left-padded with a variable amount of\n    whitespace 4) the format of values in the first column may vary for all rows,\n    including the first row 5) route output may be followed by two empty lines,\n    followed by travel warnings and/or copyright/transport agency information.\n    Status codes: 0 success; 1 generic error; 2 invalid argument; 3\n    origin/desination not found; \u003e=4 google-maps-services-python exceptions.\n    \n    positional arguments:\n      origin                start address (quote-enclosed) or latitude,longitude\n                            pair\n      destination           end address (quote-enclosed) or latitude,longitude\n                            pair\n    \n    optional arguments:\n      -h, --help            show this help message and exit\n      -b, --bus             prefer to travel by bus\n      -r, --rail            prefer to travel by rail (equivalent to train, tram,\n                            underground)\n      -n, --train           prefer to travel by train\n      -m, --tram            prefer to travel by tram\n      -u, --underground     prefer to travel by underground (a.k.a. subway)\n      -c, --car             travel by car instead of public transport\n      -k, --bicycle         travel by bicycle instead of public transport\n      -f, --foot            travel on foot instead of public transport\n      -d time_arg, --depart time_arg\n                            set departure time (see below)\n      -a time_arg, --arrive time_arg\n                            set arrival time (see below)\n      -S, --substeps        show sub-steps in output\n      -M, --multiple        show multiple routes, if available\n      -N, --no-wrap         disable word wrapping (affects command line mode only;\n                            potentially useful for scripting)\n      -R region_code, --region region_code\n                            set region bias using the specified top-level domain\n                            two-character code (ccTLD)\n      -C, --copyright       display copyright and transport agency information\n                            (see Directions API terms and conditions)\n    \n    Departure and arrival times are expressed in terms of local time at the origin\n    and destination, respectively. Times must be specified in the form\n    [[[[cc]yy]mm]dd]HH[:]MM[+N], where ccyy is the year, mm is the month (ranging\n    from 1 to 12), dd is the day (ranging from 1 to 31), HH is the hour (ranging\n    from 0 to 23) and MM is the minute (ranging from 0 to 59). When left\n    unspecified, ccyy, mm and dd values are assumed to be the current year, month\n    and day, respectively. For ambiguous times arising from daylight saving\n    transitions, it is assumed that the ambiguous time is expressed in the time\n    zone's standard time. The suffix +N may be used to offset the specified time\n    by N days. Thus, 12:00+1 means 'tomorrow at noon'.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpafoster%2Fgdir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpafoster%2Fgdir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpafoster%2Fgdir/lists"}