{"_id":"@aiir/podcast-pingback-receiver","_rev":"3-e6e646fb84beb3bd4a0465a0dccee138","name":"@aiir/podcast-pingback-receiver","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"author":{"name":"Andy Buckingham","email":"andy@aiir.com"},"dependencies":{"jsonwebtoken":"^8.3.0"},"description":"MVP Podcast Pingback receiver suitable for deployment as an AWS Lambda function","devDependencies":{"aws-sdk":"^2.327.0","eslint":"^5.6.1","eslint-config-airbnb-base":"^13.1.0","eslint-plugin-import":"^2.14.0"},"license":"MIT","main":"index.js","name":"@aiir/podcast-pingback-receiver","repository":{"type":"git","url":"git+ssh://git@github.com/aiir/podcast-pingback-receiver.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1","package":"mkdir -p lambda-package && rm -rf lambda-package/* && cp index.js package.json package-lock.json lambda-package/ && cd lambda-package && npm install --production && rm package.json package-lock.json"},"version":"1.0.0","bugs":{"url":"https://github.com/aiir/podcast-pingback-receiver/issues"},"homepage":"https://github.com/aiir/podcast-pingback-receiver#readme","_id":"@aiir/podcast-pingback-receiver@1.0.0","_npmVersion":"6.4.1","_nodeVersion":"8.10.0","_npmUser":{"name":"andybee","email":"andy@andybee.com"},"dist":{"integrity":"sha512-e6p85iKQrLfWhda7g0ObUBPYgNkSAKTmIOVg8Qns6zCnHIDbIG2EEDwB63p/CS0KU7mlg4Den+pb+AyE1994dA==","shasum":"094155b7d5b154e2e61bb20b587fe922116be609","tarball":"https://registry.npmjs.org/@aiir/podcast-pingback-receiver/-/podcast-pingback-receiver-1.0.0.tgz","fileCount":7,"unpackedSize":18335,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbt32jCRA9TVsSAnZWagAAzi4P/R8iYME6stlk/6FQgaLs\nA8/vHQf7fiX28JZdNdj+Bs2B4F79jyatRhBmIyv6haxNdV3Yj38CQ9EtZV26\noBvTvVNNlzpBZyEvL8qzBwhi0s/UiOphzAQRSzuZjqHuFwrPcEteyBWa+b/y\nKdZ42DlbdhpiXB4WCglCBTpV3qvkMYx4+170qAhj1Zpqy7rxOH0+yxM4wJqu\njZtOn+QLAE42G2a+D/PfG6JtlQM125WD8VkfuspCUAVH6ZaqWJckaJ+E7Nrn\nJcJmFdRcwagpiVMuCpWCXWt3dtLWkLsxCGpHLnkDZCKF7lFhudzSkiSxTTaM\nCKhfzHfxEYygHvbg59atjDgjEcMZB/kvCpL9jWIyTWmQtFqgIJNp8vMQKPJS\nyQFm5bD0tN5XMWUT0veW6MWYVPPORdLWo71AZBvqVSsrKytbBTLf3tozVzpG\nbBux7aExl76AHqeeRrQcj500GWsEcUqGwlHIa5OZOLia1VtaxwEhX4ZTSNjp\nAFStMseWKcpWgQ5ViV422mVcZzhCOg1LRyPDbxkfDfn9cXpu3v0TVTqDIPh0\nwKiRQTQc0UnG3FUe2uowPpfVDcTuR+cHNWFRQ4Tz19sbg3MwiGYannb1Tby+\ngS7FmHftLmmL+x6b7bv0AFH+ZxogxRXqpUmJRcDjqGUza7+izXCw0urpyKJM\nuEC5\r\n=V8rG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGNyV92nVCn6XIdoO69LAcbvmboum0TBK4srMvG9af6TAiEArNOX3xuin0fIiOTl/50+UaQcr57grVaOa71CW/2dk0A="}]},"maintainers":[{"name":"andybee","email":"andy@andybee.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/podcast-pingback-receiver_1.0.0_1538751906314_0.5240369859245406"},"_hasShrinkwrap":false},"1.0.1":{"author":{"name":"Andy Buckingham","email":"andy@aiir.com"},"dependencies":{"jsonwebtoken":"^8.3.0"},"description":"MVP Podcast Pingback receiver suitable for deployment as an AWS Lambda function","devDependencies":{"aws-sdk":"^2.327.0","eslint":"^5.6.1","eslint-config-airbnb-base":"^13.1.0","eslint-plugin-import":"^2.14.0"},"license":"MIT","main":"index.js","name":"@aiir/podcast-pingback-receiver","repository":{"type":"git","url":"git+ssh://git@github.com/aiir/podcast-pingback-receiver.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1","package":"mkdir -p lambda-package && rm -rf lambda-package/* && cp index.js package.json package-lock.json lambda-package/ && cd lambda-package && npm install --production && rm package.json package-lock.json"},"version":"1.0.1","bugs":{"url":"https://github.com/aiir/podcast-pingback-receiver/issues"},"homepage":"https://github.com/aiir/podcast-pingback-receiver#readme","_id":"@aiir/podcast-pingback-receiver@1.0.1","_npmVersion":"6.4.1","_nodeVersion":"8.10.0","_npmUser":{"name":"andybee","email":"andy@andybee.com"},"dist":{"integrity":"sha512-jLroN7H4oI5ZNQh4U+uGTYjVN2i2K3zJrfcoVpI4N1f1K3MdPG1nc5WFrPjrDJ61zilp1GcYjRQFHKBKelY0bg==","shasum":"f5a98337566aad3ef68ca932fd37ea94a266cf7d","tarball":"https://registry.npmjs.org/@aiir/podcast-pingback-receiver/-/podcast-pingback-receiver-1.0.1.tgz","fileCount":6,"unpackedSize":17737,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbt33kCRA9TVsSAnZWagAAcVcQAJ6UVc8XHKqyMJNjYims\nkWpw2bLWlHes2+Unr1qr5qMLCcB0UqeNuGbwHGnnrA8m/u+GaWbxvbftkHSV\nxM8zMOtVfCjTp6/V/MEifI0nBesHfQFGco7M/KK8k6tSf3hKoQxp5EG/Dhs7\nQ7KUcdwBJpjoZ9JnQ4rN+kxvJLf1bxMV/SMhKXkKP0v1dEdNR8XijpHatE9q\nlEEGqJ6c5LqnxiHuP6e1dVAAqp4CI6EgTMy7f2pk1Wl4+jZrwV13WZReToJK\nkoI5LsbsGCOgnx/Yp2Q3KMXwcqmMjr1BTcuDNma8FpqSl1Fe0OIMYYm9eCnK\nhqfz1srlgHyD4yvRGHDOT7XFGDlhh0i99afe+Pbmxso3F5KDBwAzQEFiykLl\nYwT3P7RJ0otVZbH2+cP6Or07RcjLtPjJRk8rfpcK9GiiLBZR7WM17keJsYSI\nTD2ASCBgfsG4ocIWw2kcBHt28Ywvs+EQECpJkY4xJ+Ktz/Of8lSqSY9BL8Y0\nXVvOx5k+zvfaTxvflqJBsUgsOgvo4RMpmuRbtu5kfM9ztF/5KMdAFcYcJhcC\n41iLuAojD0/fN8fPv+m9M/TYE3YutgObHLd53jeHfT5zClRwdUxbT3qfg2L0\nKb7JPh1DIATghfbUMxYz0rzznGGwt7CtZGA9VXyqoQI87511D307EHegyRaZ\nUHNz\r\n=fgSo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDfo7Ovn2arT2G3CR1S2AXzACuGBZhgRujkh3EkKGiuGAIhAKiblSkBQiT2nI+UZCwVD2XOjsusZ1Vhc/JN20kqCYUH"}]},"maintainers":[{"name":"andybee","email":"andy@andybee.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/podcast-pingback-receiver_1.0.1_1538751971887_0.2957179791440736"},"_hasShrinkwrap":false},"1.0.2":{"author":{"name":"Andy Buckingham","email":"andy@aiir.com"},"dependencies":{"jsonwebtoken":"^8.3.0"},"description":"MVP Podcast Pingback receiver suitable for deployment as an AWS Lambda function","devDependencies":{"aws-sdk":"^2.327.0","eslint":"^5.6.1","eslint-config-airbnb-base":"^13.1.0","eslint-plugin-import":"^2.14.0"},"license":"MIT","main":"index.js","name":"@aiir/podcast-pingback-receiver","repository":{"type":"git","url":"git+ssh://git@github.com/aiir/podcast-pingback-receiver.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1","package":"mkdir -p lambda-package && rm -rf lambda-package/* && cp index.js package.json package-lock.json lambda-package/ && cd lambda-package && npm install --production && rm package.json package-lock.json"},"version":"1.0.2","gitHead":"11fdcaca16c514c63266e10eff31a514fd1d19fa","bugs":{"url":"https://github.com/aiir/podcast-pingback-receiver/issues"},"homepage":"https://github.com/aiir/podcast-pingback-receiver#readme","_id":"@aiir/podcast-pingback-receiver@1.0.2","_npmVersion":"6.4.1","_nodeVersion":"8.10.0","_npmUser":{"name":"andybee","email":"andy@andybee.com"},"dist":{"integrity":"sha512-cvnC5sLAOGG7xjt5lvHAn0jXYHu2kH9MpPNQM83W+ABE40I1UJzVKxAPvNeD5FbWw5LAaTETsjz+crdY2e8nLw==","shasum":"770e36e30634561a78d49b152add37bcef5251d7","tarball":"https://registry.npmjs.org/@aiir/podcast-pingback-receiver/-/podcast-pingback-receiver-1.0.2.tgz","fileCount":6,"unpackedSize":19465,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbuzYwCRA9TVsSAnZWagAAMt4QAIZZJirT2ip60dSuisxK\nxNMb5exW+6h8yj68u1hPBMdDCHltV5iDlrMSXo9w+Zz5Pqzq2gR4RyKZx513\nRItZHf9eAQl3hRgf4MBPQI5fk+CsxfAD7oCewDHLH2Liris+XE4JdMpTKIwI\nq4BFsNq6oXwbF3ZWK7pYxqF3RnECFz5jasKOoItS15qxMaGutlotzHFBPukj\n9yta575VPo1NV4/dSCuL76mL2aFWmPPSlzp0phfyalD/mfBrFEtjBn1aX/JG\ns41pKVyJNFo4r9tYP3DaeUns27Ty9MIjURwJRXqRJrY19wAY0xYhOzfZkl2r\nrjgFldyHO7JK3VmgPJrsWFWFpn4Ph4KeWc690oqE95gGNNQFG6+k25mgJ037\nnr36ihWEEUhYMtZUmx/PAW7v3TwqjKzc5sgqTqfP2qo9hQADm+IVTneepAxT\nWj/fVim643H3cH5WpzNB10a0ZnSp6mx2wbP8QIqAB6kGgtTWQURlW5AlcK2O\nJrHVeymfThFLVIEV0njCuQLmWcP2twAsb/5BRiFdVZuzCMQAbYmUYSBOR3JI\nPpknyTas5SU8PH65ZADoFKERD/XOjZwmHVj8imOFBoVEA8E7zsrXaaF61AZ9\n5I8g8T7/Inlld9eSinp8vrHrOTBUVjQAdKyssFf5bUpF8MJIi1aB9d+woETQ\nJx0Y\r\n=jMB5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBQPB34uBFAtqM782lG6kJXjWm3bvUT/Qw8cQX1jIfl0AiEAwknHGVpxVio1UArRaKJunnW4Nx2VhNdXhdYCCjx+RNE="}]},"maintainers":[{"name":"andybee","email":"andy@andybee.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/podcast-pingback-receiver_1.0.2_1538995759005_0.7007274812395121"},"_hasShrinkwrap":false}},"time":{"created":"2018-10-05T15:05:06.217Z","1.0.0":"2018-10-05T15:05:06.493Z","modified":"2022-04-04T12:17:59.300Z","1.0.1":"2018-10-05T15:06:12.063Z","1.0.2":"2018-10-08T10:49:19.169Z"},"maintainers":[{"name":"andybee","email":"andy@andybee.com"}],"description":"MVP Podcast Pingback receiver suitable for deployment as an AWS Lambda function","homepage":"https://github.com/aiir/podcast-pingback-receiver#readme","repository":{"type":"git","url":"git+ssh://git@github.com/aiir/podcast-pingback-receiver.git"},"author":{"name":"Andy Buckingham","email":"andy@aiir.com"},"bugs":{"url":"https://github.com/aiir/podcast-pingback-receiver/issues"},"license":"MIT","readme":"# Podcast Pingback Receiver Lambda Function\n\nA minimum viable [Podcast Pingback](https://podping.info/) receiver suitable for\ndeployment as an [AWS Lambda](https://aws.amazon.com/lambda/) function.\n\nThe function parses and validates an incoming submission against the [Podcast\nPingback v1](https://podping.info/specification/1) specification and, if valid,\nsaves the incoming request in to an [S3 bucket](https://aws.amazon.com/s3/).\n\nThe contents of the bucket can then be processed by an independent process to\ninterpret the submissions as your organisation requires.\n\nThis is intended to remain a minimal implementation for demonstration purposes.\n\n## Installation\n\n```\n$ npm install @aiir\\podcast-pingback-lambda\n```\n\n## Methodology\n\nThe Lambda function will save all valid incoming requests to an S3 bucket. The\nbody will be the original JSON object that was received and it's key is made up\nof the date and time of the incoming request and the first component of the\nlistener's UUID.\n\nIf a `listener` object is included in the request, the `listener_token` value\nreturned in the response is a\n[JSON Web Token](https://tools.ietf.org/html/rfc7519) which includes the\nlistener's UUID, encoded using the secret supplied to the Lambda function.\n\nFor example, with the function configured with a secret of `MySpecialSecret`, an\nincoming request of:\n\n```\nPOST /pingback HTTP/1.1\nContent-Type: application/json\nDate: Mon, 8 Oct 2018 08:17:22 GMT\n\n{ \"uuid\": \"2eefaf08-d43e-46f9-ac53-520c881e59b8\",\n  \"content\": \"https://alice.example.net/episode-1.mp3\",\n  \"listener\": {\n    \"date_of_birth\": \"1984-11-21\"\n  },\n  \"events\": [\n    {\n      \"event\": \"resume\",\n      \"date\": \"2018-01-01T09:00:00Z\",\n      \"offset\": 0\n    }\n  ]\n}\n```\n\nwould elicit the response:\n\n```\nHTTP/1.1 201 Created\nContent-Type: application/json\nDate: Mon, 8 Oct 2018 08:17:22 GMT\n\n{ \"status\": \"ok\",\n  \"listener_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiMmVlZmFmMDgtZDQzZS00NmY5LWFjNTMtNTIwYzg4MWU1OWI4In0.vgUQ_HS7EwswfmXkD4f0koUBcrCmiiv0hkkcacY3oCc\"\n}\n```\n\nAn object with the key `2018-10-08-08:17:22-2eefaf08.json` would be written to\nthe S3 bucket, with the same body as the request:\n\n```\n{ \"uuid\": \"2eefaf08-d43e-46f9-ac53-520c881e59b8\",\n  \"content\": \"https://alice.example.net/episode-1.mp3\",\n  \"listener\": {\n    \"date_of_birth\": \"1984-11-21\"\n  },\n  \"events\": [\n    {\n      \"event\": \"resume\",\n      \"date\": \"2018-01-01T09:00:00Z\",\n      \"offset\": 0\n    }\n  ]\n}\n```\n\n## Deployment\n\n### Using CloudFormation\n\nThe easiest way to get started is to use the supplied\n[CloudFormation](https://aws.amazon.com/cloudformation/) script, which sets up\nthe required AWS components for you.\n\nThis may not be desirable for your environment as it uses AWS defaults and\ncreates fresh resources for all the required components, where you may already\nhave some of the required infastructure setup. Always be sure to check what's\ninvolved in a CloudFormation script before deploying it in to your environment.\n\n1. From the same directory you installed this Node.js module in to, run the\n   package process to create a zip file suitable for upload to AWS:\n\n   ```\n   $ npm run package\n   ```\n\n   This creates a `lambda-package` directory which contains the minimum required\n   files for the Lambda function, removing unnecessary files that exist in the\n   root of the project to keep the Lambda function package lean.\n\n2. Ensuring you have the [AWS CLI](https://aws.amazon.com/cli/) installed, run\n   the following command to upload the local function package to an S3 bucket of\n   your choosing and regenerate the template with the S3 URL injected, ready for\n   deployment.\n\n   Be sure to replace `my-bucket` with name of a bucket your current AWS profile\n   has write access to. This is a temporary location for the code before Lambda\n   deployment takes a copy of it, so you can delete it later and don't\n   necessarily need a bespoke bucket for. This is also not the bucket requests\n   will be saved to, that is automatically created later by the CloudFormation.\n\n   ```\n   aws cloudformation package \\\n       --template template.json \\\n       --s3-bucket my-bucket \\\n       --output-template-file packaged-template.json \\\n       --use-json\n   ```\n\n3. Once complete, you now need to request CloudFormation deploy the stack which\n   will create the AWS components and deploy the receiver ready for use.\n\n   Be sure to replace `MySecret` with a good 512-byte secret, which will be used\n   by function to encrypt a listener token.\n\n   The `--capabilities CAPABILITY_IAM` line gives permission for this\n   CloudFormation template to create IAM roles. This is used by the template to\n   allow the Lambda function write access to only the S3 bucket it creates for\n   storing incoming requests.\n\n   ```\n   aws cloudformation deploy \\\n       --template-file packaged-template.json \\\n       --stack-name podcast-pingback-stack \\\n       --parameter-overrides TokenSecret=MySecret \\\n       --capabilities CAPABILITY_IAM\n   ```\n\n4. When this finishes successfully, you will have an HTTPS accessible Podcast\n   Pingback receiver.\n\n   To find the public URL for your receiver, visit the\n   [AWS Console](https://console.aws.amazon.com/console/), then go to API\n   Gateway, find the specific gateway for this project (usually part of the name\n   will include `podcast-pingback-stack` unless you chose an alternative stack\n   name in Step 3), then going to Stages, then `Prod`.\n\n   On this page you will see the root URL for the stage (e.g.\n   `https://e9cddzz12i.execute-api.eu-west-1.amazonaws.com/Prod`). Add the\n   resource path `/receiver` to the end for the specific resource to get the\n   full URL.\n\n   API Gateway offers the ability to replace this default host + stage with a\n   [custom domain](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html),\n   which gives you a better looking receiver URL.\n\n5. Finally, don't forget to advertise your Podcast Pingback receiver URL in the\n   RSS feed(s) of your podcast(s). This is done by adding the following line\n   within your <pingback:receiver> element.\n\n   ```\n   <pingback:receiver>https://e9cddzz12i.execute-api.eu-west-1.amazonaws.com/Prod/receiver</pingback:receiver>\n   ```\n\n### Manually\n\nIf you'd prefer to integrate this script in to an established AWS environment,\nor perform the steps manually, you will need to setup the Lambda function, an S3\nbucket for storing incoming requests, a role to allow the function to write to\nthe S3 bucket, and an API Gateway to allow HTTPS access to the function.\n\nThe function itself requires a Node 8.10 runtime, and the following environment\nvariables to be configured:\n\n<dl>\n  <dt><code>SECRET</code></dt>\n  <dd>\n    The function generates JSON Web Tokens to identify unique clients. It\n    requires a \"secret\" to encode the contents. Set to a random, long string.\n  </dd>\n  <dt><code>BUCKET</code></dt>\n  <dd>\n    This is the name of the bucket you created in Step 1, so the function knows\n    where to dump valid requests.\n  </dd>\n</dl>\n\n## Authors\n\n- Created by [@andybee](https://twitter.com/andybee)\n\n## License\n\nMIT\n","readmeFilename":"README.md"}