{"id":13413992,"url":"https://github.com/eduncan911/podcast","last_synced_at":"2025-04-13T06:37:32.230Z","repository":{"id":56517910,"uuid":"80723913","full_name":"eduncan911/podcast","owner":"eduncan911","description":"iTunes and RSS 2.0 Podcast Generator in Golang","archived":false,"fork":false,"pushed_at":"2020-11-04T21:44:28.000Z","size":386,"stargazers_count":131,"open_issues_count":5,"forks_count":35,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-07-31T20:53:13.761Z","etag":null,"topics":["go","golang","itunes","podcast"],"latest_commit_sha":null,"homepage":"","language":"Go","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/eduncan911.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-02T12:45:04.000Z","updated_at":"2024-07-26T14:51:34.000Z","dependencies_parsed_at":"2022-08-15T20:10:54.420Z","dependency_job_id":null,"html_url":"https://github.com/eduncan911/podcast","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduncan911%2Fpodcast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduncan911%2Fpodcast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduncan911%2Fpodcast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduncan911%2Fpodcast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eduncan911","download_url":"https://codeload.github.com/eduncan911/podcast/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248675352,"owners_count":21143763,"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":["go","golang","itunes","podcast"],"created_at":"2024-07-30T20:01:54.649Z","updated_at":"2025-04-13T06:37:32.194Z","avatar_url":"https://github.com/eduncan911.png","language":"Go","funding_links":[],"categories":["Specific Formats","文本处理","Text Processing","文本处理`解析和操作文本的代码库`","Template Engines","Bot Building"],"sub_categories":["RSS","查询语","HTTP Clients"],"readme":"[![GoDoc](https://godoc.org/github.com/eduncan911/podcast?status.svg)](https://godoc.org/github.com/eduncan911/podcast)\n[![Build Status](https://github.com/eduncan911/podcast/workflows/go-cicd/badge.svg)](https://github.com/eduncan911/podcast/actions?workflow=go-cicd)\n[![Coverage Status](https://coveralls.io/repos/github/eduncan911/podcast/badge.svg?branch=master)](https://coveralls.io/github/eduncan911/podcast?branch=master)\n[![Go Report Card](https://goreportcard.com/badge/github.com/eduncan911/podcast)](https://goreportcard.com/report/github.com/eduncan911/podcast)\n[![MIT License](https://img.shields.io/npm/l/mediaelement.svg)](https://eduncan911.mit-license.org/)\n\n# podcast\nPackage podcast generates a fully compliant iTunes and RSS 2.0 podcast feed\nfor GoLang using a simple API.\n\nFull documentation with detailed examples located at \u003ca href=\"https://godoc.org/github.com/eduncan911/podcast\"\u003ehttps://godoc.org/github.com/eduncan911/podcast\u003c/a\u003e\n\n### Usage\nTo use, `go get` and `import` the package like your typical GoLang library.\n\n\t$ go get -u github.com/eduncan911/podcast\n\t\n\timport \"github.com/eduncan911/podcast\"\n\nThe API exposes a number of method receivers on structs that implements the\nlogic required to comply with the specifications and ensure a compliant feed.\nA number of overrides occur to help with iTunes visibility of your episodes.\n\nNotably, the `Podcast.AddItem` function performs most\nof the heavy lifting by taking the `Item` input and performing\nvalidation, overrides and duplicate setters through the feed.\n\nFull detailed Examples of the API are at \u003ca href=\"https://godoc.org/github.com/eduncan911/podcast\"\u003ehttps://godoc.org/github.com/eduncan911/podcast\u003c/a\u003e.\n\n### Go Modules\nThis library is supported on GoLang 1.7 and higher.\n\nWe have implemented Go Modules support and the CI pipeline shows it working with\nnew installs, tested with Go 1.13.  To keep 1.7 compatibility, we use\n`go mod vendor` to maintain the `vendor/` folder for older 1.7 and later runtimes.\n\nIf either runtime has an issue, please create an Issue and I will address.\n\n### Extensibility\nFor version 1.x, you are not restricted in having full control over your feeds.\nYou may choose to skip the API methods and instead use the structs directly.  The\nfields have been grouped by RSS 2.0 and iTunes fields with iTunes specific fields\nall prefixed with the letter `I`.\n\nHowever, do note that the 2.x version currently in progress will break this\nextensibility and enforce API methods going forward. This is to ensure that the feed\ncan both be marshalled, and unmarshalled back and forth (current 1.x branch can only\nbe unmarshalled - hence the work for 2.x).\n\n### Fuzzing Inputs\n`go-fuzz` has been added in 1.4.1, covering all exported API methods.  They have been\nran extensively and no issues have come out of them yet (most tests were ran overnight,\nover about 11 hours with zero crashes).\n\nIf you wish to help fuzz the inputs, with Go 1.13 or later you can run `go-fuzz` on any\nof the inputs.\n\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz-build\n\tgo get -u github.com/eduncan911/podcast\n\tcd $GOPATH/src/github.com/eduncan911/podcast\n\tgo-fuzz-build\n\tgo-fuzz -func FuzzPodcastAddItem\n\nTo obtain a list of available funcs to pass, just run `go-fuzz` without any parameters:\n\n\t$ go-fuzz\n\t2020/02/13 07:27:32 -func flag not provided, but multiple fuzz functions available:\n\tFuzzItemAddDuration, FuzzItemAddEnclosure, FuzzItemAddImage, FuzzItemAddPubDate,\n\tFuzzItemAddSummary, FuzzPodcastAddAtomLink, FuzzPodcastAddAuthor, FuzzPodcastAddCategory,\n\tFuzzPodcastAddImage, FuzzPodcastAddItem, FuzzPodcastAddLastBuildDate, FuzzPodcastAddPubDate,\n\tFuzzPodcastAddSubTitle, FuzzPodcastAddSummary, FuzzPodcastBytes, FuzzPodcastEncode,\n\tFuzzPodcastNew\n\nIf you do find an issue, please raise an issue immediately and I will quickly address.\n\n### Roadmap\nThe 1.x branch is now mostly in maintenance mode, open to PRs.  This means no\nmore planned features on the 1.x feature branch is expected. With the success of 6\niTunes-accepted podcasts I have published with this library, and with the feedback from\nthe community, the 1.x releases are now considered stable.\n\nThe 2.x branch's primary focus is to allow for bi-direction marshalling both ways.\nCurrently, the 1.x branch only allows unmarshalling to a serial feed.  An attempt to marshall\na serialized feed back into a Podcast form will error or not work correctly.  Note that while\nthe 2.x branch is targeted to remain backwards compatible, it is true if using the public\nAPI funcs to set parameters only.  Several of the underlying public fields are being removed\nin order to accommodate the marshalling of serialized data.  Therefore, a version 2.x is denoted\nfor this release.\n\n### Versioning\nWe use SemVer versioning schema.  You can rest assured that pulling 1.x branches will\nremain backwards compatible now and into the future.\n\nHowever, the new 2.x branch, while keeping the same API, is expected break those that\nbypass the API methods and use the underlying public properties instead.\n\n### Release Notes\nv1.4.2\n\n\t* Slim down Go Modules for consumers (#32)\n\nv1.4.1\n\n\t* Implement fuzz logic testing of exported funcs (#31)\n\t* Upgrade CICD Pipeline Tooling (#31)\n\t* Update documentation for 1.x and 2.3 (#31)\n\t* Allow godoc2ghmd to run without network (#31)\n\nv1.4.0\n\n\t* Add Go Modules, Update vendor folder (#26, #25)\n\t* Add C.I. GitHub Actions (#25)\n\t* Add additional error checks found by linters (#25)\n\t* Go Fmt enclosure_test.go (#25)\n\nv1.3.2\n\n\t* Correct count len of UTF8 strings (#9)\n\t* Implement duration parser (#8)\n\t* Fix Github and GoDocs Markdown (#14)\n\t* Move podcast.go Private Methods to Respected Files (#12)\n\t* Allow providing GUID on Podcast (#15)\n\nv1.3.1\n\n\t* increased itunes compliance after feedback from Apple:\n\t  - specified what categories should be set with AddCategory().\n\t  - enforced title and link as part of Image.\n\t* added Podcast.AddAtomLink() for more broad compliance to readers.\n\nv1.3.0\n\n\t* fixes Item.Duration being set incorrectly.\n\t* changed Item.AddEnclosure() parameter definition (Bytes not Seconds!).\n\t* added Item.AddDuration formatting and override.\n\t* added more documentation surrounding Item.Enclosure{}\n\nv1.2.1\n\n\t* added Podcast.AddSubTitle() and truncating to 64 chars.\n\t* added a number of Guards to protect against empty fields.\n\nv1.2.0\n\n\t* added Podcast.AddPubDate() and Podcast.AddLastBuildDate() overrides.\n\t* added Item.AddImage() to mask some cumbersome addition of IImage.\n\t* added Item.AddPubDate to simply datetime setters.\n\t* added more examples (mostly around Item struct).\n\t* tweaked some documentation.\n\nv1.1.0\n\n\t* Enabling CDATA in ISummary fields for Podcast and Channel.\n\nv1.0.0\n\n\t* Initial release.\n\t* Full documentation, full examples and complete code coverage.\n\n### References\nRSS 2.0: \u003ca href=\"https://cyber.harvard.edu/rss/rss.html\"\u003ehttps://cyber.harvard.edu/rss/rss.html\u003c/a\u003e\n\nPodcasts: \u003ca href=\"https://help.apple.com/itc/podcasts_connect/#/itca5b22233\"\u003ehttps://help.apple.com/itc/podcasts_connect/#/itca5b22233\u003c/a\u003e\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\n// ResponseWriter example using Podcast.Encode(w io.Writer).\n\t//\n\thttpHandler := func(w http.ResponseWriter, r *http.Request) {\n\t\n\t    // instantiate a new Podcast\n\t    p := podcast.New(\n\t        \"eduncan911 Podcasts\",\n\t        \"http://eduncan911.com/\",\n\t        \"An example Podcast\",\n\t        \u0026pubDate, \u0026updatedDate,\n\t    )\n\t\n\t    // add some channel properties\n\t    p.AddAuthor(\"Jane Doe\", \"me@janedoe.com\")\n\t    p.AddAtomLink(\"http://eduncan911.com/feed.rss\")\n\t    p.AddImage(\"http://janedoe.com/i.jpg\")\n\t    p.AddSummary(`link \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e`)\n\t    p.IExplicit = \"no\"\n\t\n\t    for i := int64(1); i \u003c 3; i++ {\n\t        n := strconv.FormatInt(i, 10)\n\t        d := pubDate.AddDate(0, 0, int(i))\n\t\n\t        // create an Item\n\t        item := podcast.Item{\n\t            Title:       \"Episode \" + n,\n\t            Link:        \"http://example.com/\" + n + \".mp3\",\n\t            Description: \"Description for Episode \" + n,\n\t            PubDate:     \u0026d,\n\t        }\n\t        item.AddImage(\"http://example.com/episode-\" + n + \".png\")\n\t        item.AddSummary(`item \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e`)\n\t        // add a Download to the Item\n\t        item.AddEnclosure(\"http://e.com/\"+n+\".mp3\", podcast.MP3, 55*(i+1))\n\t\n\t        // add the Item and check for validation errors\n\t        if _, err := p.AddItem(item); err != nil {\n\t            fmt.Println(item.Title, \": error\", err.Error())\n\t            return\n\t        }\n\t    }\n\t\n\t    // set the Content Type to that of XML\n\t    w.Header().Set(\"Content-Type\", \"application/xml\")\n\t\n\t    // finally, Encode and write the Podcast to the ResponseWriter.\n\t    //\n\t    // a simple pattern is to handle any errors within this check.\n\t    // alternatively if using middleware, you can just return\n\t    // the Podcast entity as it also implements the io.Writer interface\n\t    // that complies with several middleware packages.\n\t    if err := p.Encode(w); err != nil {\n\t        http.Error(w, err.Error(), http.StatusInternalServerError)\n\t    }\n\t}\n\t\n\trr := httptest.NewRecorder()\n\thttpHandler(rr, nil)\n\tos.Stdout.Write(rr.Body.Bytes())\n\t// Output:\n\t// \u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\t// \u003crss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\" xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\"\u003e\n\t//   \u003cchannel\u003e\n\t//     \u003ctitle\u003eeduncan911 Podcasts\u003c/title\u003e\n\t//     \u003clink\u003ehttp://eduncan911.com/\u003c/link\u003e\n\t//     \u003cdescription\u003eAn example Podcast\u003c/description\u003e\n\t//     \u003cgenerator\u003ego podcast v1.3.1 (github.com/eduncan911/podcast)\u003c/generator\u003e\n\t//     \u003clanguage\u003een-us\u003c/language\u003e\n\t//     \u003clastBuildDate\u003eMon, 06 Feb 2017 08:21:52 +0000\u003c/lastBuildDate\u003e\n\t//     \u003cmanagingEditor\u003eme@janedoe.com (Jane Doe)\u003c/managingEditor\u003e\n\t//     \u003cpubDate\u003eSat, 04 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//     \u003cimage\u003e\n\t//       \u003curl\u003ehttp://janedoe.com/i.jpg\u003c/url\u003e\n\t//       \u003ctitle\u003eeduncan911 Podcasts\u003c/title\u003e\n\t//       \u003clink\u003ehttp://eduncan911.com/\u003c/link\u003e\n\t//     \u003c/image\u003e\n\t//     \u003catom:link href=\"http://eduncan911.com/feed.rss\" rel=\"self\" type=\"application/rss+xml\"\u003e\u003c/atom:link\u003e\n\t//     \u003citunes:author\u003eme@janedoe.com (Jane Doe)\u003c/itunes:author\u003e\n\t//     \u003citunes:summary\u003e\u003c![CDATA[link \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e]]\u003e\u003c/itunes:summary\u003e\n\t//     \u003citunes:image href=\"http://janedoe.com/i.jpg\"\u003e\u003c/itunes:image\u003e\n\t//     \u003citunes:explicit\u003eno\u003c/itunes:explicit\u003e\n\t//     \u003citem\u003e\n\t//       \u003cguid\u003ehttp://e.com/1.mp3\u003c/guid\u003e\n\t//       \u003ctitle\u003eEpisode 1\u003c/title\u003e\n\t//       \u003clink\u003ehttp://example.com/1.mp3\u003c/link\u003e\n\t//       \u003cdescription\u003eDescription for Episode 1\u003c/description\u003e\n\t//       \u003cpubDate\u003eSun, 05 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//       \u003cenclosure url=\"http://e.com/1.mp3\" length=\"110\" type=\"audio/mpeg\"\u003e\u003c/enclosure\u003e\n\t//       \u003citunes:author\u003eme@janedoe.com (Jane Doe)\u003c/itunes:author\u003e\n\t//       \u003citunes:summary\u003e\u003c![CDATA[item \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e]]\u003e\u003c/itunes:summary\u003e\n\t//       \u003citunes:image href=\"http://example.com/episode-1.png\"\u003e\u003c/itunes:image\u003e\n\t//     \u003c/item\u003e\n\t//     \u003citem\u003e\n\t//       \u003cguid\u003ehttp://e.com/2.mp3\u003c/guid\u003e\n\t//       \u003ctitle\u003eEpisode 2\u003c/title\u003e\n\t//       \u003clink\u003ehttp://example.com/2.mp3\u003c/link\u003e\n\t//       \u003cdescription\u003eDescription for Episode 2\u003c/description\u003e\n\t//       \u003cpubDate\u003eMon, 06 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//       \u003cenclosure url=\"http://e.com/2.mp3\" length=\"165\" type=\"audio/mpeg\"\u003e\u003c/enclosure\u003e\n\t//       \u003citunes:author\u003eme@janedoe.com (Jane Doe)\u003c/itunes:author\u003e\n\t//       \u003citunes:summary\u003e\u003c![CDATA[item \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e]]\u003e\u003c/itunes:summary\u003e\n\t//       \u003citunes:image href=\"http://example.com/episode-2.png\"\u003e\u003c/itunes:image\u003e\n\t//     \u003c/item\u003e\n\t//   \u003c/channel\u003e\n\t// \u003c/rss\u003e\n```\n\n\u003c/details\u003e\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\n// instantiate a new Podcast\n\tp := podcast.New(\n\t    \"Sample Podcasts\",\n\t    \"http://example.com/\",\n\t    \"An example Podcast\",\n\t    \u0026createdDate, \u0026updatedDate,\n\t)\n\t\n\t// add some channel properties\n\tp.ISubtitle = \"A simple Podcast\"\n\tp.AddSummary(`link \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e`)\n\tp.AddImage(\"http://example.com/podcast.jpg\")\n\tp.AddAuthor(\"Jane Doe\", \"jane.doe@example.com\")\n\tp.AddAtomLink(\"http://example.com/atom.rss\")\n\t\n\tfor i := int64(9); i \u003c 11; i++ {\n\t    n := strconv.FormatInt(i, 10)\n\t    d := pubDate.AddDate(0, 0, int(i))\n\t\n\t    // create an Item\n\t    item := podcast.Item{\n\t        Title:       \"Episode \" + n,\n\t        Description: \"Description for Episode \" + n,\n\t        ISubtitle:   \"A simple episode \" + n,\n\t        PubDate:     \u0026d,\n\t    }\n\t    item.AddImage(\"http://example.com/episode-\" + n + \".png\")\n\t    item.AddSummary(`item k \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e`)\n\t    // add a Download to the Item\n\t    item.AddEnclosure(\"http://example.com/\"+n+\".mp3\", podcast.MP3, 55*(i+1))\n\t\n\t    // add the Item and check for validation errors\n\t    if _, err := p.AddItem(item); err != nil {\n\t        os.Stderr.WriteString(\"item validation error: \" + err.Error())\n\t    }\n\t}\n\t\n\t// Podcast.Encode writes to an io.Writer\n\tif err := p.Encode(os.Stdout); err != nil {\n\t    fmt.Println(\"error writing to stdout:\", err.Error())\n\t}\n\t\n\t// Output:\n\t// \u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\t// \u003crss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\" xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\"\u003e\n\t//   \u003cchannel\u003e\n\t//     \u003ctitle\u003eSample Podcasts\u003c/title\u003e\n\t//     \u003clink\u003ehttp://example.com/\u003c/link\u003e\n\t//     \u003cdescription\u003eAn example Podcast\u003c/description\u003e\n\t//     \u003cgenerator\u003ego podcast v1.3.1 (github.com/eduncan911/podcast)\u003c/generator\u003e\n\t//     \u003clanguage\u003een-us\u003c/language\u003e\n\t//     \u003clastBuildDate\u003eMon, 06 Feb 2017 08:21:52 +0000\u003c/lastBuildDate\u003e\n\t//     \u003cmanagingEditor\u003ejane.doe@example.com (Jane Doe)\u003c/managingEditor\u003e\n\t//     \u003cpubDate\u003eWed, 01 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//     \u003cimage\u003e\n\t//       \u003curl\u003ehttp://example.com/podcast.jpg\u003c/url\u003e\n\t//       \u003ctitle\u003eSample Podcasts\u003c/title\u003e\n\t//       \u003clink\u003ehttp://example.com/\u003c/link\u003e\n\t//     \u003c/image\u003e\n\t//     \u003catom:link href=\"http://example.com/atom.rss\" rel=\"self\" type=\"application/rss+xml\"\u003e\u003c/atom:link\u003e\n\t//     \u003citunes:author\u003ejane.doe@example.com (Jane Doe)\u003c/itunes:author\u003e\n\t//     \u003citunes:subtitle\u003eA simple Podcast\u003c/itunes:subtitle\u003e\n\t//     \u003citunes:summary\u003e\u003c![CDATA[link \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e]]\u003e\u003c/itunes:summary\u003e\n\t//     \u003citunes:image href=\"http://example.com/podcast.jpg\"\u003e\u003c/itunes:image\u003e\n\t//     \u003citem\u003e\n\t//       \u003cguid\u003ehttp://example.com/9.mp3\u003c/guid\u003e\n\t//       \u003ctitle\u003eEpisode 9\u003c/title\u003e\n\t//       \u003clink\u003ehttp://example.com/9.mp3\u003c/link\u003e\n\t//       \u003cdescription\u003eDescription for Episode 9\u003c/description\u003e\n\t//       \u003cpubDate\u003eMon, 13 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//       \u003cenclosure url=\"http://example.com/9.mp3\" length=\"550\" type=\"audio/mpeg\"\u003e\u003c/enclosure\u003e\n\t//       \u003citunes:author\u003ejane.doe@example.com (Jane Doe)\u003c/itunes:author\u003e\n\t//       \u003citunes:subtitle\u003eA simple episode 9\u003c/itunes:subtitle\u003e\n\t//       \u003citunes:summary\u003e\u003c![CDATA[item k \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e]]\u003e\u003c/itunes:summary\u003e\n\t//       \u003citunes:image href=\"http://example.com/episode-9.png\"\u003e\u003c/itunes:image\u003e\n\t//     \u003c/item\u003e\n\t//     \u003citem\u003e\n\t//       \u003cguid\u003ehttp://example.com/10.mp3\u003c/guid\u003e\n\t//       \u003ctitle\u003eEpisode 10\u003c/title\u003e\n\t//       \u003clink\u003ehttp://example.com/10.mp3\u003c/link\u003e\n\t//       \u003cdescription\u003eDescription for Episode 10\u003c/description\u003e\n\t//       \u003cpubDate\u003eTue, 14 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//       \u003cenclosure url=\"http://example.com/10.mp3\" length=\"605\" type=\"audio/mpeg\"\u003e\u003c/enclosure\u003e\n\t//       \u003citunes:author\u003ejane.doe@example.com (Jane Doe)\u003c/itunes:author\u003e\n\t//       \u003citunes:subtitle\u003eA simple episode 10\u003c/itunes:subtitle\u003e\n\t//       \u003citunes:summary\u003e\u003c![CDATA[item k \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e]]\u003e\u003c/itunes:summary\u003e\n\t//       \u003citunes:image href=\"http://example.com/episode-10.png\"\u003e\u003c/itunes:image\u003e\n\t//     \u003c/item\u003e\n\t//   \u003c/channel\u003e\n\t// \u003c/rss\u003e\n```\n\n\u003c/details\u003e\n\n## Table of Contents\n\n* [Imported Packages](#pkg-imports)\n* [Index](#pkg-index)\n* [Examples](#pkg-examples)\n\n## \u003ca name=\"pkg-imports\"\u003eImported Packages\u003c/a\u003e\n\n- [github.com/pkg/errors](https://godoc.org/github.com/pkg/errors)\n\n## \u003ca name=\"pkg-index\"\u003eIndex\u003c/a\u003e\n* [type AtomLink](#AtomLink)\n* [type Author](#Author)\n* [type Enclosure](#Enclosure)\n* [type EnclosureType](#EnclosureType)\n  * [func (et EnclosureType) String() string](#EnclosureType.String)\n* [type ICategory](#ICategory)\n* [type IImage](#IImage)\n* [type ISummary](#ISummary)\n* [type Image](#Image)\n* [type Item](#Item)\n  * [func (i \\*Item) AddDuration(durationInSeconds int64)](#Item.AddDuration)\n  * [func (i \\*Item) AddEnclosure(url string, enclosureType EnclosureType, lengthInBytes int64)](#Item.AddEnclosure)\n  * [func (i \\*Item) AddImage(url string)](#Item.AddImage)\n  * [func (i \\*Item) AddPubDate(datetime \\*time.Time)](#Item.AddPubDate)\n  * [func (i \\*Item) AddSummary(summary string)](#Item.AddSummary)\n* [type Podcast](#Podcast)\n  * [func New(title, link, description string, pubDate, lastBuildDate \\*time.Time) Podcast](#New)\n  * [func (p \\*Podcast) AddAtomLink(href string)](#Podcast.AddAtomLink)\n  * [func (p \\*Podcast) AddAuthor(name, email string)](#Podcast.AddAuthor)\n  * [func (p \\*Podcast) AddCategory(category string, subCategories []string)](#Podcast.AddCategory)\n  * [func (p \\*Podcast) AddImage(url string)](#Podcast.AddImage)\n  * [func (p \\*Podcast) AddItem(i Item) (int, error)](#Podcast.AddItem)\n  * [func (p \\*Podcast) AddLastBuildDate(datetime \\*time.Time)](#Podcast.AddLastBuildDate)\n  * [func (p \\*Podcast) AddPubDate(datetime \\*time.Time)](#Podcast.AddPubDate)\n  * [func (p \\*Podcast) AddSubTitle(subTitle string)](#Podcast.AddSubTitle)\n  * [func (p \\*Podcast) AddSummary(summary string)](#Podcast.AddSummary)\n  * [func (p \\*Podcast) Bytes() []byte](#Podcast.Bytes)\n  * [func (p \\*Podcast) Encode(w io.Writer) error](#Podcast.Encode)\n  * [func (p \\*Podcast) String() string](#Podcast.String)\n* [type TextInput](#TextInput)\n\n#### \u003ca name=\"pkg-examples\"\u003eExamples\u003c/a\u003e\n* [Item.AddDuration](#example_Item_AddDuration)\n* [Item.AddPubDate](#example_Item_AddPubDate)\n* [New](#example_New)\n* [Podcast.AddAuthor](#example_Podcast_AddAuthor)\n* [Podcast.AddCategory](#example_Podcast_AddCategory)\n* [Podcast.AddImage](#example_Podcast_AddImage)\n* [Podcast.AddItem](#example_Podcast_AddItem)\n* [Podcast.AddLastBuildDate](#example_Podcast_AddLastBuildDate)\n* [Podcast.AddPubDate](#example_Podcast_AddPubDate)\n* [Podcast.AddSummary](#example_Podcast_AddSummary)\n* [Podcast.Bytes](#example_Podcast_Bytes)\n* [Package (HttpHandlers)](#example__httpHandlers)\n* [Package (IoWriter)](#example__ioWriter)\n\n#### \u003ca name=\"pkg-files\"\u003ePackage files\u003c/a\u003e\n[atomlink.go](./atomlink.go) [author.go](./author.go) [doc.go](./doc.go) [enclosure.go](./enclosure.go) [image.go](./image.go) [item.go](./item.go) [itunes.go](./itunes.go) [podcast.go](./podcast.go) [textinput.go](./textinput.go) \n\n## \u003ca name=\"AtomLink\"\u003etype\u003c/a\u003e [AtomLink](./atomlink.go#L6-L11)\n``` go\ntype AtomLink struct {\n    XMLName xml.Name `xml:\"atom:link\"`\n    HREF    string   `xml:\"href,attr\"`\n    Rel     string   `xml:\"rel,attr\"`\n    Type    string   `xml:\"type,attr\"`\n}\n```\nAtomLink represents the Atom reference link.\n\n## \u003ca name=\"Author\"\u003etype\u003c/a\u003e [Author](./author.go#L8-L12)\n``` go\ntype Author struct {\n    XMLName xml.Name `xml:\"itunes:owner\"`\n    Name    string   `xml:\"itunes:name\"`\n    Email   string   `xml:\"itunes:email\"`\n}\n```\nAuthor represents a named author and email.\n\nFor iTunes compliance, both Name and Email are required.\n\n## \u003ca name=\"Enclosure\"\u003etype\u003c/a\u003e [Enclosure](./enclosure.go#L46-L65)\n``` go\ntype Enclosure struct {\n    XMLName xml.Name `xml:\"enclosure\"`\n\n    // URL is the downloadable url for the content. (Required)\n    URL string `xml:\"url,attr\"`\n\n    // Length is the size in Bytes of the download. (Required)\n    Length int64 `xml:\"-\"`\n    // LengthFormatted is the size in Bytes of the download. (Required)\n    //\n    // This field gets overwritten with the API when setting Length.\n    LengthFormatted string `xml:\"length,attr\"`\n\n    // Type is MIME type encoding of the download. (Required)\n    Type EnclosureType `xml:\"-\"`\n    // TypeFormatted is MIME type encoding of the download. (Required)\n    //\n    // This field gets overwritten with the API when setting Type.\n    TypeFormatted string `xml:\"type,attr\"`\n}\n```\nEnclosure represents a download enclosure.\n\n## \u003ca name=\"EnclosureType\"\u003etype\u003c/a\u003e [EnclosureType](./enclosure.go#L21)\n``` go\ntype EnclosureType int\n```\nEnclosureType specifies the type of the enclosure.\n\n``` go\nconst (\n    M4A EnclosureType = iota\n    M4V\n    MP4\n    MP3\n    MOV\n    PDF\n    EPUB\n)\n```\nEnclosureType specifies the type of the enclosure.\n\n### \u003ca name=\"EnclosureType.String\"\u003efunc\u003c/a\u003e (EnclosureType) [String](./enclosure.go#L24)\n``` go\nfunc (et EnclosureType) String() string\n```\nString returns the MIME type encoding of the specified EnclosureType.\n\n## \u003ca name=\"ICategory\"\u003etype\u003c/a\u003e [ICategory](./itunes.go#L9-L13)\n``` go\ntype ICategory struct {\n    XMLName     xml.Name `xml:\"itunes:category\"`\n    Text        string   `xml:\"text,attr\"`\n    ICategories []*ICategory\n}\n```\nICategory is a 2-tier classification system for iTunes.\n\n## \u003ca name=\"IImage\"\u003etype\u003c/a\u003e [IImage](./itunes.go#L23-L26)\n``` go\ntype IImage struct {\n    XMLName xml.Name `xml:\"itunes:image\"`\n    HREF    string   `xml:\"href,attr\"`\n}\n```\nIImage represents an iTunes image.\n\nPodcast feeds contain artwork that is a minimum size of\n1400 x 1400 pixels and a maximum size of 3000 x 3000 pixels,\n72 dpi, in JPEG or PNG format with appropriate file\nextensions (.jpg, .png), and in the RGB colorspace. To optimize\nimages for mobile devices, Apple recommends compressing your\nimage files.\n\n## \u003ca name=\"ISummary\"\u003etype\u003c/a\u003e [ISummary](./itunes.go#L31-L34)\n``` go\ntype ISummary struct {\n    XMLName xml.Name `xml:\"itunes:summary\"`\n    Text    string   `xml:\",cdata\"`\n}\n```\nISummary is a 4000 character rich-text field for the itunes:summary tag.\n\nThis is rendered as CDATA which allows for HTML tags such as `\u003ca href=\"\"\u003e`.\n\n## \u003ca name=\"Image\"\u003etype\u003c/a\u003e [Image](./image.go#L13-L21)\n``` go\ntype Image struct {\n    XMLName     xml.Name `xml:\"image\"`\n    URL         string   `xml:\"url\"`\n    Title       string   `xml:\"title\"`\n    Link        string   `xml:\"link\"`\n    Description string   `xml:\"description,omitempty\"`\n    Width       int      `xml:\"width,omitempty\"`\n    Height      int      `xml:\"height,omitempty\"`\n}\n```\nImage represents an image.\n\nPodcast feeds contain artwork that is a minimum size of\n1400 x 1400 pixels and a maximum size of 3000 x 3000 pixels,\n72 dpi, in JPEG or PNG format with appropriate file\nextensions (.jpg, .png), and in the RGB colorspace. To optimize\nimages for mobile devices, Apple recommends compressing your\nimage files.\n\n## \u003ca name=\"Item\"\u003etype\u003c/a\u003e [Item](./item.go#L27-L51)\n``` go\ntype Item struct {\n    XMLName          xml.Name   `xml:\"item\"`\n    GUID             string     `xml:\"guid\"`\n    Title            string     `xml:\"title\"`\n    Link             string     `xml:\"link\"`\n    Description      string     `xml:\"description\"`\n    Author           *Author    `xml:\"-\"`\n    AuthorFormatted  string     `xml:\"author,omitempty\"`\n    Category         string     `xml:\"category,omitempty\"`\n    Comments         string     `xml:\"comments,omitempty\"`\n    Source           string     `xml:\"source,omitempty\"`\n    PubDate          *time.Time `xml:\"-\"`\n    PubDateFormatted string     `xml:\"pubDate,omitempty\"`\n    Enclosure        *Enclosure\n\n    // https://help.apple.com/itc/podcasts_connect/#/itcb54353390\n    IAuthor            string `xml:\"itunes:author,omitempty\"`\n    ISubtitle          string `xml:\"itunes:subtitle,omitempty\"`\n    ISummary           *ISummary\n    IImage             *IImage\n    IDuration          string `xml:\"itunes:duration,omitempty\"`\n    IExplicit          string `xml:\"itunes:explicit,omitempty\"`\n    IIsClosedCaptioned string `xml:\"itunes:isClosedCaptioned,omitempty\"`\n    IOrder             string `xml:\"itunes:order,omitempty\"`\n}\n```\nItem represents a single entry in a podcast.\n\nArticle minimal requirements are:\n- Title\n- Description\n- Link\n\nAudio minimal requirements are:\n- Title\n- Description\n- Enclosure (HREF, Type and Length all required)\n\nRecommendations:\n- Setting the minimal fields sets most of other fields, including iTunes.\n- Use the Published time.Time setting instead of PubDate.\n- Always set an Enclosure.Length, to be nice to your downloaders.\n- Use Enclosure.Type instead of setting TypeFormatted for valid extensions.\n\n### \u003ca name=\"Item.AddDuration\"\u003efunc\u003c/a\u003e (\\*Item) [AddDuration](./item.go#L104)\n``` go\nfunc (i *Item) AddDuration(durationInSeconds int64)\n```\nAddDuration adds the duration to the iTunes duration field.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\ni := podcast.Item{\n\t    Title:       \"item title\",\n\t    Description: \"item desc\",\n\t    Link:        \"item link\",\n\t}\n\td := int64(533)\n\t\n\t// add the Duration in Seconds\n\ti.AddDuration(d)\n\t\n\tfmt.Println(i.IDuration)\n\t// Output:\n\t// 8:53\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Item.AddEnclosure\"\u003efunc\u003c/a\u003e (\\*Item) [AddEnclosure](./item.go#L54-L55)\n``` go\nfunc (i *Item) AddEnclosure(\n    url string, enclosureType EnclosureType, lengthInBytes int64)\n```\nAddEnclosure adds the downloadable asset to the podcast Item.\n\n### \u003ca name=\"Item.AddImage\"\u003efunc\u003c/a\u003e (\\*Item) [AddImage](./item.go#L72)\n``` go\nfunc (i *Item) AddImage(url string)\n```\nAddImage adds the image as an iTunes-only IImage.  RSS 2.0 does not have\nthe specification of Images at the Item level.\n\nPodcast feeds contain artwork that is a minimum size of\n1400 x 1400 pixels and a maximum size of 3000 x 3000 pixels,\n72 dpi, in JPEG or PNG format with appropriate file\nextensions (.jpg, .png), and in the RGB colorspace. To optimize\nimages for mobile devices, Apple recommends compressing your\nimage files.\n\n### \u003ca name=\"Item.AddPubDate\"\u003efunc\u003c/a\u003e (\\*Item) [AddPubDate](./item.go#L81)\n``` go\nfunc (i *Item) AddPubDate(datetime *time.Time)\n```\nAddPubDate adds the datetime as a parsed PubDate.\n\nUTC time is used by default.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", nil, nil)\n\ti := podcast.Item{\n\t    Title:       \"item title\",\n\t    Description: \"item desc\",\n\t    Link:        \"item link\",\n\t}\n\td := pubDate.AddDate(0, 0, -11)\n\t\n\t// add the pub date\n\ti.AddPubDate(\u0026d)\n\t\n\t// before adding\n\tif i.PubDate != nil {\n\t    fmt.Println(i.PubDateFormatted, *i.PubDate)\n\t}\n\t\n\t// this should not override with Podcast.PubDate\n\tif _, err := p.AddItem(i); err != nil {\n\t    fmt.Println(err)\n\t}\n\t\n\t// after adding item\n\tfmt.Println(i.PubDateFormatted, *i.PubDate)\n\t// Output:\n\t// Tue, 24 Jan 2017 08:21:52 +0000 2017-01-24 08:21:52 +0000 UTC\n\t// Tue, 24 Jan 2017 08:21:52 +0000 2017-01-24 08:21:52 +0000 UTC\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Item.AddSummary\"\u003efunc\u003c/a\u003e (\\*Item) [AddSummary](./item.go#L92)\n``` go\nfunc (i *Item) AddSummary(summary string)\n```\nAddSummary adds the iTunes summary.\n\nLimit: 4000 characters\n\nNote that this field is a CDATA encoded field which allows for rich text\nsuch as html links: `\u003ca href=\"\u003ca href=\"http://www.apple.com\"\u003ehttp://www.apple.com\u003c/a\u003e\"\u003eApple\u003c/a\u003e`.\n\n## \u003ca name=\"Podcast\"\u003etype\u003c/a\u003e [Podcast](./podcast.go#L20-L59)\n``` go\ntype Podcast struct {\n    XMLName        xml.Name `xml:\"channel\"`\n    Title          string   `xml:\"title\"`\n    Link           string   `xml:\"link\"`\n    Description    string   `xml:\"description\"`\n    Category       string   `xml:\"category,omitempty\"`\n    Cloud          string   `xml:\"cloud,omitempty\"`\n    Copyright      string   `xml:\"copyright,omitempty\"`\n    Docs           string   `xml:\"docs,omitempty\"`\n    Generator      string   `xml:\"generator,omitempty\"`\n    Language       string   `xml:\"language,omitempty\"`\n    LastBuildDate  string   `xml:\"lastBuildDate,omitempty\"`\n    ManagingEditor string   `xml:\"managingEditor,omitempty\"`\n    PubDate        string   `xml:\"pubDate,omitempty\"`\n    Rating         string   `xml:\"rating,omitempty\"`\n    SkipHours      string   `xml:\"skipHours,omitempty\"`\n    SkipDays       string   `xml:\"skipDays,omitempty\"`\n    TTL            int      `xml:\"ttl,omitempty\"`\n    WebMaster      string   `xml:\"webMaster,omitempty\"`\n    Image          *Image\n    TextInput      *TextInput\n    AtomLink       *AtomLink\n\n    // https://help.apple.com/itc/podcasts_connect/#/itcb54353390\n    IAuthor     string `xml:\"itunes:author,omitempty\"`\n    ISubtitle   string `xml:\"itunes:subtitle,omitempty\"`\n    ISummary    *ISummary\n    IBlock      string `xml:\"itunes:block,omitempty\"`\n    IImage      *IImage\n    IDuration   string  `xml:\"itunes:duration,omitempty\"`\n    IExplicit   string  `xml:\"itunes:explicit,omitempty\"`\n    IComplete   string  `xml:\"itunes:complete,omitempty\"`\n    INewFeedURL string  `xml:\"itunes:new-feed-url,omitempty\"`\n    IOwner      *Author // Author is formatted for itunes as-is\n    ICategories []*ICategory\n\n    Items []*Item\n    // contains filtered or unexported fields\n}\n```\nPodcast represents a podcast.\n\n### \u003ca name=\"New\"\u003efunc\u003c/a\u003e [New](./podcast.go#L65-L66)\n``` go\nfunc New(title, link, description string,\n    pubDate, lastBuildDate *time.Time) Podcast\n```\nNew instantiates a Podcast with required parameters.\n\nNil-able fields are optional but recommended as they are formatted\nto the expected proper formats.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\nti, l, d := \"title\", \"link\", \"description\"\n\t\n\t// instantiate a new Podcast\n\tp := podcast.New(ti, l, d, \u0026pubDate, \u0026updatedDate)\n\t\n\tfmt.Println(p.Title, p.Link, p.Description, p.Language)\n\tfmt.Println(p.PubDate, p.LastBuildDate)\n\t// Output:\n\t// title link description en-us\n\t// Sat, 04 Feb 2017 08:21:52 +0000 Mon, 06 Feb 2017 08:21:52 +0000\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.AddAtomLink\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddAtomLink](./podcast.go#L94)\n``` go\nfunc (p *Podcast) AddAtomLink(href string)\n```\nAddAtomLink adds a FQDN reference to an atom feed.\n\n### \u003ca name=\"Podcast.AddAuthor\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddAuthor](./podcast.go#L82)\n``` go\nfunc (p *Podcast) AddAuthor(name, email string)\n```\nAddAuthor adds the specified Author to the podcast.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", nil, nil)\n\t\n\t// add the Author\n\tp.AddAuthor(\"the name\", \"me@test.com\")\n\t\n\tfmt.Println(p.ManagingEditor)\n\tfmt.Println(p.IAuthor)\n\t// Output:\n\t// me@test.com (the name)\n\t// me@test.com (the name)\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.AddCategory\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddCategory](./podcast.go#L183)\n``` go\nfunc (p *Podcast) AddCategory(category string, subCategories []string)\n```\nAddCategory adds the category to the Podcast.\n\nICategory can be listed multiple times.\n\nCalling this method multiple times will APPEND the category to the existing\nlist, if any, including ICategory.\n\nNote that Apple iTunes has a specific list of categories that only can be\nused and will invalidate the feed if deviated from the list.  That list is\nas follows.\n\n\t* Arts\n\t  * Design\n\t  * Fashion \u0026 Beauty\n\t  * Food\n\t  * Literature\n\t  * Performing Arts\n\t  * Visual Arts\n\t* Business\n\t  * Business News\n\t  * Careers\n\t  * Investing\n\t  * Management \u0026 Marketing\n\t  * Shopping\n\t* Comedy\n\t* Education\n\t  * Education Technology\n\t  * Higher Education\n\t  * K-12\n\t  * Language Courses\n\t  * Training\n\t* Games \u0026 Hobbies\n\t  * Automotive\n\t  * Aviation\n\t  * Hobbies\n\t  * Other Games\n\t  * Video Games\n\t* Government \u0026 Organizations\n\t  * Local\n\t  * National\n\t  * Non-Profit\n\t  * Regional\n\t* Health\n\t  * Alternative Health\n\t  * Fitness \u0026 Nutrition\n\t  * Self-Help\n\t  * Sexuality\n\t* Kids \u0026 Family\n\t* Music\n\t* News \u0026 Politics\n\t* Religion \u0026 Spirituality\n\t  * Buddhism\n\t  * Christianity\n\t  * Hinduism\n\t  * Islam\n\t  * Judaism\n\t  * Other\n\t  * Spirituality\n\t* Science \u0026 Medicine\n\t  * Medicine\n\t  * Natural Sciences\n\t  * Social Sciences\n\t* Society \u0026 Culture\n\t  * History\n\t  * Personal Journals\n\t  * Philosophy\n\t  * Places \u0026 Travel\n\t* Sports \u0026 Recreation\n\t  * Amateur\n\t  * College \u0026 High School\n\t  * Outdoor\n\t  * Professional\n\t* Technology\n\t  * Gadgets\n\t  * Podcasting\n\t  * Software How-To\n\t  * Tech News\n\t* TV \u0026 Film\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", nil, nil)\n\t\n\t// add the Category\n\tp.AddCategory(\"Bombay\", nil)\n\tp.AddCategory(\"American\", []string{\"Longhair\", \"Shorthair\"})\n\tp.AddCategory(\"Siamese\", nil)\n\t\n\tfmt.Println(len(p.ICategories), len(p.ICategories[1].ICategories))\n\tfmt.Println(p.Category)\n\t// Output:\n\t// 3 2\n\t// Bombay,American,Siamese\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.AddImage\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddImage](./podcast.go#L214)\n``` go\nfunc (p *Podcast) AddImage(url string)\n```\nAddImage adds the specified Image to the Podcast.\n\nPodcast feeds contain artwork that is a minimum size of\n1400 x 1400 pixels and a maximum size of 3000 x 3000 pixels,\n72 dpi, in JPEG or PNG format with appropriate file\nextensions (.jpg, .png), and in the RGB colorspace. To optimize\nimages for mobile devices, Apple recommends compressing your\nimage files.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", nil, nil)\n\t\n\t// add the Image\n\tp.AddImage(\"http://example.com/image.jpg\")\n\t\n\tif p.Image != nil \u0026\u0026 p.IImage != nil {\n\t    fmt.Println(p.Image.URL)\n\t    fmt.Println(p.IImage.HREF)\n\t}\n\t// Output:\n\t// http://example.com/image.jpg\n\t// http://example.com/image.jpg\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.AddItem\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddItem](./podcast.go#L267)\n``` go\nfunc (p *Podcast) AddItem(i Item) (int, error)\n```\nAddItem adds the podcast episode.  It returns a count of Items added or any\nerrors in validation that may have occurred.\n\nThis method takes the \"itunes overrides\" approach to populating\nitunes tags according to the overrides rules in the specification.\nThis not only complies completely with iTunes parsing rules; but, it also\ndisplays what is possible to be set on an individual episode level – if you\nwish to have more fine grain control over your content.\n\nThis method imposes strict validation of the Item being added to confirm\nto Podcast and iTunes specifications.\n\nArticle minimal requirements are:\n\n\t* Title\n\t* Description\n\t* Link\n\nAudio, Video and Downloads minimal requirements are:\n\n\t* Title\n\t* Description\n\t* Enclosure (HREF, Type and Length all required)\n\nThe following fields are always overwritten (don't set them):\n\n\t* GUID\n\t* PubDateFormatted\n\t* AuthorFormatted\n\t* Enclosure.TypeFormatted\n\t* Enclosure.LengthFormatted\n\nRecommendations:\n\n\t* Just set the minimal fields: the rest get set for you.\n\t* Always set an Enclosure.Length, to be nice to your downloaders.\n\t* Follow Apple's best practices to enrich your podcasts:\n\t  \u003ca href=\"https://help.apple.com/itc/podcasts_connect/#/itc2b3780e76\"\u003ehttps://help.apple.com/itc/podcasts_connect/#/itc2b3780e76\u003c/a\u003e\n\t* For specifications of itunes tags, see:\n\t  \u003ca href=\"https://help.apple.com/itc/podcasts_connect/#/itcb54353390\"\u003ehttps://help.apple.com/itc/podcasts_connect/#/itcb54353390\u003c/a\u003e\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", \u0026pubDate, \u0026updatedDate)\n\tp.AddAuthor(\"the name\", \"me@test.com\")\n\tp.AddImage(\"http://example.com/image.jpg\")\n\t\n\t// create an Item\n\tdate := pubDate.AddDate(0, 0, 77)\n\titem := podcast.Item{\n\t    Title:       \"Episode 1\",\n\t    Description: \"Description for Episode 1\",\n\t    ISubtitle:   \"A simple episode 1\",\n\t    PubDate:     \u0026date,\n\t}\n\titem.AddEnclosure(\n\t    \"http://example.com/1.mp3\",\n\t    podcast.MP3,\n\t    183,\n\t)\n\titem.AddSummary(\"See more at \u003ca href=\\\"http://example.com\\\"\u003eHere\u003c/a\u003e\")\n\t\n\t// add the Item\n\tif _, err := p.AddItem(item); err != nil {\n\t    fmt.Println(\"item validation error: \" + err.Error())\n\t}\n\t\n\tif len(p.Items) != 1 {\n\t    fmt.Println(\"expected 1 item in the collection\")\n\t}\n\tpp := p.Items[0]\n\tfmt.Println(\n\t    pp.GUID, pp.Title, pp.Link, pp.Description, pp.Author,\n\t    pp.AuthorFormatted, pp.Category, pp.Comments, pp.Source,\n\t    pp.PubDate, pp.PubDateFormatted, *pp.Enclosure,\n\t    pp.IAuthor, pp.IDuration, pp.IExplicit, pp.IIsClosedCaptioned,\n\t    pp.IOrder, pp.ISubtitle, pp.ISummary)\n\t// Output:\n\t// http://example.com/1.mp3 Episode 1 http://example.com/1.mp3 Description for Episode 1 \u0026{{ }  me@test.com (the name)}     2017-04-22 08:21:52 +0000 UTC Sat, 22 Apr 2017 08:21:52 +0000 {{ } http://example.com/1.mp3 183 183 audio/mpeg audio/mpeg} me@test.com (the name)     A simple episode 1 \u0026{{ } See more at \u003ca href=\"http://example.com\"\u003eHere\u003c/a\u003e}\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.AddLastBuildDate\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddLastBuildDate](./podcast.go#L344)\n``` go\nfunc (p *Podcast) AddLastBuildDate(datetime *time.Time)\n```\nAddLastBuildDate adds the datetime as a parsed PubDate.\n\nUTC time is used by default.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", nil, nil)\n\td := pubDate.AddDate(0, 0, -7)\n\t\n\tp.AddLastBuildDate(\u0026d)\n\t\n\tfmt.Println(p.LastBuildDate)\n\t// Output:\n\t// Sat, 28 Jan 2017 08:21:52 +0000\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.AddPubDate\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddPubDate](./podcast.go#L337)\n``` go\nfunc (p *Podcast) AddPubDate(datetime *time.Time)\n```\nAddPubDate adds the datetime as a parsed PubDate.\n\nUTC time is used by default.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", nil, nil)\n\td := pubDate.AddDate(0, 0, -5)\n\t\n\tp.AddPubDate(\u0026d)\n\t\n\tfmt.Println(p.PubDate)\n\t// Output:\n\t// Mon, 30 Jan 2017 08:21:52 +0000\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.AddSubTitle\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddSubTitle](./podcast.go#L353)\n``` go\nfunc (p *Podcast) AddSubTitle(subTitle string)\n```\nAddSubTitle adds the iTunes subtitle that is displayed with the title\nin iTunes.\n\nNote that this field should be just a few words long according to Apple.\nThis method will truncate the string to 64 chars if too long with \"...\"\n\n### \u003ca name=\"Podcast.AddSummary\"\u003efunc\u003c/a\u003e (\\*Podcast) [AddSummary](./podcast.go#L371)\n``` go\nfunc (p *Podcast) AddSummary(summary string)\n```\nAddSummary adds the iTunes summary.\n\nLimit: 4000 characters\n\nNote that this field is a CDATA encoded field which allows for rich text\nsuch as html links: `\u003ca href=\"\u003ca href=\"http://www.apple.com\"\u003ehttp://www.apple.com\u003c/a\u003e\"\u003eApple\u003c/a\u003e`.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\"title\", \"link\", \"description\", nil, nil)\n\t\n\t// add a summary\n\tp.AddSummary(`A very cool podcast with a long summary!\n\t\n\tSee more at our website: \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e\n\t`)\n\t\n\tif p.ISummary != nil {\n\t    fmt.Println(p.ISummary.Text)\n\t}\n\t// Output:\n\t// A very cool podcast with a long summary!\n\t//\n\t// See more at our website: \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.Bytes\"\u003efunc\u003c/a\u003e (\\*Podcast) [Bytes](./podcast.go#L386)\n``` go\nfunc (p *Podcast) Bytes() []byte\n```\nBytes returns an encoded []byte slice.\n\n#### Example:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand code.\u003c/summary\u003e\n\n```go\np := podcast.New(\n\t    \"eduncan911 Podcasts\",\n\t    \"http://eduncan911.com/\",\n\t    \"An example Podcast\",\n\t    \u0026pubDate, \u0026updatedDate,\n\t)\n\tp.AddAuthor(\"Jane Doe\", \"me@janedoe.com\")\n\tp.AddImage(\"http://janedoe.com/i.jpg\")\n\tp.AddSummary(`A very cool podcast with a long summary using Bytes()!\n\t\n\tSee more at our website: \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e\n\t`)\n\t\n\tfor i := int64(5); i \u003c 7; i++ {\n\t    n := strconv.FormatInt(i, 10)\n\t    d := pubDate.AddDate(0, 0, int(i+3))\n\t\n\t    item := podcast.Item{\n\t        Title:       \"Episode \" + n,\n\t        Link:        \"http://example.com/\" + n + \".mp3\",\n\t        Description: \"Description for Episode \" + n,\n\t        PubDate:     \u0026d,\n\t    }\n\t    if _, err := p.AddItem(item); err != nil {\n\t        fmt.Println(item.Title, \": error\", err.Error())\n\t        break\n\t    }\n\t}\n\t\n\t// call Podcast.Bytes() to return a byte array\n\tos.Stdout.Write(p.Bytes())\n\t\n\t// Output:\n\t// \u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\t// \u003crss version=\"2.0\" xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\"\u003e\n\t//   \u003cchannel\u003e\n\t//     \u003ctitle\u003eeduncan911 Podcasts\u003c/title\u003e\n\t//     \u003clink\u003ehttp://eduncan911.com/\u003c/link\u003e\n\t//     \u003cdescription\u003eAn example Podcast\u003c/description\u003e\n\t//     \u003cgenerator\u003ego podcast v1.3.1 (github.com/eduncan911/podcast)\u003c/generator\u003e\n\t//     \u003clanguage\u003een-us\u003c/language\u003e\n\t//     \u003clastBuildDate\u003eMon, 06 Feb 2017 08:21:52 +0000\u003c/lastBuildDate\u003e\n\t//     \u003cmanagingEditor\u003eme@janedoe.com (Jane Doe)\u003c/managingEditor\u003e\n\t//     \u003cpubDate\u003eSat, 04 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//     \u003cimage\u003e\n\t//       \u003curl\u003ehttp://janedoe.com/i.jpg\u003c/url\u003e\n\t//       \u003ctitle\u003eeduncan911 Podcasts\u003c/title\u003e\n\t//       \u003clink\u003ehttp://eduncan911.com/\u003c/link\u003e\n\t//     \u003c/image\u003e\n\t//     \u003citunes:author\u003eme@janedoe.com (Jane Doe)\u003c/itunes:author\u003e\n\t//     \u003citunes:summary\u003e\u003c![CDATA[A very cool podcast with a long summary using Bytes()!\n\t//\n\t// See more at our website: \u003ca href=\"http://example.com\"\u003eexample.com\u003c/a\u003e\n\t// ]]\u003e\u003c/itunes:summary\u003e\n\t//     \u003citunes:image href=\"http://janedoe.com/i.jpg\"\u003e\u003c/itunes:image\u003e\n\t//     \u003citem\u003e\n\t//       \u003cguid\u003ehttp://example.com/5.mp3\u003c/guid\u003e\n\t//       \u003ctitle\u003eEpisode 5\u003c/title\u003e\n\t//       \u003clink\u003ehttp://example.com/5.mp3\u003c/link\u003e\n\t//       \u003cdescription\u003eDescription for Episode 5\u003c/description\u003e\n\t//       \u003cpubDate\u003eSun, 12 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//       \u003citunes:author\u003eme@janedoe.com (Jane Doe)\u003c/itunes:author\u003e\n\t//       \u003citunes:image href=\"http://janedoe.com/i.jpg\"\u003e\u003c/itunes:image\u003e\n\t//     \u003c/item\u003e\n\t//     \u003citem\u003e\n\t//       \u003cguid\u003ehttp://example.com/6.mp3\u003c/guid\u003e\n\t//       \u003ctitle\u003eEpisode 6\u003c/title\u003e\n\t//       \u003clink\u003ehttp://example.com/6.mp3\u003c/link\u003e\n\t//       \u003cdescription\u003eDescription for Episode 6\u003c/description\u003e\n\t//       \u003cpubDate\u003eMon, 13 Feb 2017 08:21:52 +0000\u003c/pubDate\u003e\n\t//       \u003citunes:author\u003eme@janedoe.com (Jane Doe)\u003c/itunes:author\u003e\n\t//       \u003citunes:image href=\"http://janedoe.com/i.jpg\"\u003e\u003c/itunes:image\u003e\n\t//     \u003c/item\u003e\n\t//   \u003c/channel\u003e\n\t// \u003c/rss\u003e\n```\n\n\u003c/details\u003e\n\n### \u003ca name=\"Podcast.Encode\"\u003efunc\u003c/a\u003e (\\*Podcast) [Encode](./podcast.go#L391)\n``` go\nfunc (p *Podcast) Encode(w io.Writer) error\n```\nEncode writes the bytes to the io.Writer stream in RSS 2.0 specification.\n\n### \u003ca name=\"Podcast.String\"\u003efunc\u003c/a\u003e (\\*Podcast) [String](./podcast.go#L410)\n``` go\nfunc (p *Podcast) String() string\n```\nString encodes the Podcast state to a string.\n\n## \u003ca name=\"TextInput\"\u003etype\u003c/a\u003e [TextInput](./textinput.go#L6-L12)\n``` go\ntype TextInput struct {\n    XMLName     xml.Name `xml:\"textInput\"`\n    Title       string   `xml:\"title\"`\n    Description string   `xml:\"description\"`\n    Name        string   `xml:\"name\"`\n    Link        string   `xml:\"link\"`\n}\n```\nTextInput represents text inputs.\n\n- - -\nGenerated by [godoc2ghmd](https://github.com/eduncan911/godoc2ghmd)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feduncan911%2Fpodcast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feduncan911%2Fpodcast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feduncan911%2Fpodcast/lists"}