{"id":22546606,"url":"https://github.com/prx/prx-podagent","last_synced_at":"2025-04-10T00:52:42.857Z","repository":{"id":46220637,"uuid":"99137425","full_name":"PRX/prx-podagent","owner":"PRX","description":"User-agent parser for common podcast clients","archived":false,"fork":false,"pushed_at":"2025-04-09T15:40:28.000Z","size":4763,"stargazers_count":20,"open_issues_count":3,"forks_count":7,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-04-10T00:52:38.175Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/PRX.png","metadata":{"files":{"readme":"README.md","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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-02T16:16:17.000Z","updated_at":"2025-04-09T15:39:56.000Z","dependencies_parsed_at":"2024-01-09T20:03:41.639Z","dependency_job_id":"894ea939-ab5e-44e0-accc-1fe6a7365292","html_url":"https://github.com/PRX/prx-podagent","commit_stats":{"total_commits":129,"total_committers":6,"mean_commits":21.5,"dds":0.06976744186046513,"last_synced_commit":"a09bf1e4e7fe2c8951db88bc3456b06568f53040"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fprx-podagent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fprx-podagent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fprx-podagent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fprx-podagent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PRX","download_url":"https://codeload.github.com/PRX/prx-podagent/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248137995,"owners_count":21053775,"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","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":[],"created_at":"2024-12-07T15:08:20.139Z","updated_at":"2025-04-10T00:52:42.821Z","avatar_url":"https://github.com/PRX.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PRX Podcast User-Agent Parser\n\n[![license](https://img.shields.io/github/license/PRX/prx-podagent.svg)](LICENSE)\n[![npm](https://img.shields.io/npm/v/prx-podagent.svg)](https://www.npmjs.com/package/prx-podagent)\n[![npm](https://img.shields.io/npm/dt/prx-podagent.svg)](https://www.npmjs.com/package/prx-podagent)\n![Node.js CI](https://github.com/PRX/prx-podagent/workflows/Node.js%20CI/badge.svg)\n\n**[prx.github.io/prx-podagent](https://prx.github.io/prx-podagent/)**\n\n## Description\n\nBasic User-Agent string parser that includes some basic podcasting apps.  This\nproject is intended to help parse/group requests for analytics purposes, not for\nbrowser feature detection.\n\nThe included `agents.lock.yml` also includes name/type/os IDs, in case you want\nto normalize the strings in your database.\n\n## Install\n\nJust `npm install --save prx-podagent`. Or to use outside of node, just grab a\ndatabase file out of the `db/` directory.\n\n## Usage\n\n```node\nconst podagent = require('prx-podagent');\nconst agent = podagent.parse('some-string');\nif (agent) {\n  console.log('Match:', agent.name, agent.type, agent.os);\n} else {\n  console.log('Did not match any known agents');\n}\n```\n\nOr to DIY use the json lock file:\n\n```javascript\n  $.getJSON('agents.json', function(db) {\n    db.agents.forEach(function(a) {\n      a.regex = new RegExp(a.regex, a.ignorecase ? 'i' : undefined);\n    });\n\n    var str = decodeURIComponent('some-agent-string');\n    var agent = db.agents.find(function(a) { return a.regex.test(str); });\n    if (agent) {\n      console.log('matched!', agent);\n    } else {\n      console.log('no match for:', str);\n    }\n  });\n```\n\nOr in Ruby:\n\n```ruby\nrequire 'yaml'\n\nDB = YAML.load_file('db/agents.lock.yml')\ndef match_agent(str)\n  str = URI.unescape(str)\n  DB['agents'].find { |a| Regexp.new(a['regex'], a['ignorecase'] ? 'i' : nil).match(str) }\u0026.tap do |match|\n    %w(name type os).each { |k| match[k] = DB['tags'][match[k]] }\n  end\nend\n\nputs match_agent('Pandora/1812.2 Android/5.1.1 ford (ExoPlayerLib2.8.2)').inspect\n# {\"regex\"=\u003e\"/^HardCast.+CFNetwork/\", \"name\"=\u003e\"HardCast\", \"type\"=\u003e\"Mobile App\", \"os\"=\u003e\"iOS\"}\nputs match_agent('blah blah blah').inspect\n# nil\n```\n\nOr in PHP:\n\n```php\n\u003c?php\nrequire_once 'spyc.php';\n$DB = Spyc::YAMLLoad('db/agents.lock.yml');\n\nfunction match_agent($str) {\n  global $DB;\n\n  $str = urldecode($str)\n  $match = NULL;\n  foreach ($DB['agents'] as $agent) {\n    $pattern = '/' . $agent['regex'] . '/' . ($agent['ignorecase'] ? 'i' : '');\n    if (preg_match($pattern, $str)) {\n      $match = $agent;\n      foreach (array('name', 'type', 'os') as $key) {\n        $match[$key] = $DB['tags'][$match[$key]];\n      }\n      break;\n    }\n  }\n  return $match;\n}\n\nvar_dump(match_agent('Pandora/1812.2 Android/5.1.1 ford (ExoPlayerLib2.8.2)'));\n?\u003e\n```\n\n### URI Encodings\n\nNote: it's fairly common to see URI encodings in user agent strings.  And often\ndepends on your particular server setup.  The regexps in this library are\nintended to be used on the fully-uri-decoded `User-Agent` string.  So you should\nalways `decodeURIComponent()` the value before attempting to match.\n\nI've also seen a mix of encoded/decoded spaces within a single user agent\nstring.  Where the first space has been encoded to `%20`, but subsequent ones\nare not.  So URI decoding is probably a good idea anyways.\n\n## Development\n\nBasic tests are located in the `/test` directory, and can be run with `npm test`.\n\nAdditionally, there is a `test/support/testagents.csv` file containing some actual\nproduction logs.  The \"coverage\" and \"omissions\" tests use this file to check that\nthe database file accounts for all the major known user agents.\n\nTo add a new user agent:\n\n1. Edit the `db/agents.yml` file to include your new regular expression, plus\n   an example user-agent string or two.\n2. Run `npm test` (or just `mocha test/examples-test.js`) to test that your\n   example strings match the regexp.\n3. Run `npm run lock` to regenerate the `db/agents.lock.yml`.  This file normalizes\n   the text tags/labels shared between the various matchers.  Check that your\n   change didn't add any unexpected new tags (if you accidentally changed the\n   case of a label or something).\n4. Create a pull request to this repo.\n\nTo release a new version:\n\n1. Get or set a `GITHUB_TOKEN` ENV (needed for [release-it](https://github.com/release-it/release-it#github-releases))\n2. Run `npm run release`\n3. Select whether this is a major/minor patch, according to [semantic versioning](https://semver.org/)\n4. Select \"yes\" on publishing to NPM, Pushing, and creating a Github Release\n\n## License\n\n[MIT License](LICENSE)\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (git checkout -b my-new-feature)\n3. Commit your changes (git commit -am 'Add some feature')\n4. Push to the branch (git push origin my-new-feature)\n5. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprx%2Fprx-podagent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprx%2Fprx-podagent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprx%2Fprx-podagent/lists"}