feed/lib.rs
1// This file is part of feed.
2//
3// Copyright © 2015-2017 Chris Palmer <pennstate5013@gmail.com>
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published by
7// the Free Software Foundation; either version 3 of the License, or
8// (at your option) any later version.
9
10
11#![doc(html_root_url = "https://docs.rs/feed/")]
12#![deny(missing_docs)]
13
14
15//! # feed 3.0
16//!
17//! This Library is for parsing through a channels field and creating a `Feed`
18//! struct containing all elements of a `Channel` based on the channels spec.
19//!
20//! ## Usage
21//! Put this in your Cargo.toml:
22//!
23//! ```Toml
24//! [dependencies]
25//! feed = "3.0"
26//! ```
27//!
28//! And put this in your crate root:
29//!
30//! ```
31//! extern crate feed;
32//! ```
33//!
34//! ## Examples
35//!
36//! ### Reading Feeds
37//!
38//! ```
39//! extern crate rss;
40//! extern crate feed;
41//!
42//! use feed::{FromUrl, ChannelGetters};
43//! use rss::Channel;
44//!
45//! fn main()
46//! {
47//! let url = "https://feedpress.me/usererror.xml";
48//!
49//! let channel = Channel::from_url(url).unwrap();
50//! println!("Feed Title: {:?}", channel.title());
51//! }
52//! ```
53//!
54//! ### Writing Feeds
55//!
56//! ```
57//! extern crate feed;
58//!
59//! use feed::ChannelBuilder;
60//!
61//! fn main()
62//! {
63//! let description = "Ogg Vorbis audio versions of The Linux ".to_owned()
64//! + "Action Show! A show that covers everything geeks care about in "
65//! + "the computer industry. Get a solid dose of Linux, gadgets, news "
66//! + "events and much more!";
67//!
68//! let channel = ChannelBuilder::new()
69//! .title("The Linux Action Show! OGG")
70//! .link("http://www.jupiterbroadcasting.com")
71//! .description(description.as_ref())
72//! .finalize().unwrap();
73//!
74//! println!("Feed: {:?}", channel.to_string());
75//! }
76//! ```
77//!
78//! ### Validating Feeds
79//!
80//! ```
81//! extern crate feed;
82//!
83//! use feed::ChannelBuilder;
84//!
85//! fn main()
86//! {
87//! let description = "Ogg Vorbis audio versions of The Linux ".to_owned()
88//! + "Action Show! A show that covers everything geeks care about in "
89//! + "the computer industry. Get a solid dose of Linux, gadgets, news "
90//! + "events and much more!";
91//!
92//! let channel = ChannelBuilder::new()
93//! .title("The Linux Action Show! OGG")
94//! .link("http://www.jupiterbroadcasting.com")
95//! .description(description.as_ref())
96//! .validate().unwrap()
97//! .finalize().unwrap();
98//!
99//! println!("Feed: {:?}", channel.to_string());
100//! }
101//! ```
102//!
103//! ```
104//! extern crate rss;
105//! extern crate feed;
106//!
107//! use feed::{FromUrl, Validate};
108//! use rss::Channel;
109//!
110//! fn main()
111//! {
112//! let url = "https://feedpress.me/usererror.xml";
113//!
114//! let channel = Channel::from_url(url).unwrap();
115//! channel.validate().unwrap();
116//! }
117//! ```
118
119extern crate chrono;
120extern crate curl;
121extern crate mime;
122extern crate rss;
123extern crate url;
124
125
126mod enums;
127pub mod extension;
128pub mod channel;
129mod utils;
130
131
132use rss::{Category, Channel, Cloud, Enclosure, Guid, Image, Item, Source, TextInput};
133use rss::extension::itunes::{ITunesChannelExtension, ITunesItemExtension};
134
135/// The Getter functions for `Category`
136pub trait CategoryGetters
137{
138 /// Get the category that exists under `Category`.
139 fn name(&self) -> String;
140
141
142 /// Get the optional domain that exists under `Category`.
143 fn domain(&self) -> Option<String>;
144}
145
146
147/// This `CategoryBuilder` struct creates the `Category`.
148#[derive(Clone, Default)]
149pub struct CategoryBuilder
150{
151 name: String,
152 domain: Option<String>,
153}
154
155
156/// From Url function for `Channel`
157pub trait FromUrl
158{
159 /// Construct a `Channel` from a `Url`.
160 fn from_url(url: &str) -> Result<Channel, String>;
161}
162
163
164/// Validate function for `Channel`
165pub trait Validate
166{
167 /// Validate `Channel`
168 fn validate(&self) -> Result<Channel, String>;
169}
170
171
172/// The Getter functions for `Channel`
173pub trait ChannelGetters
174{
175 /// Get the title that exists under `Channel`.
176 fn title(&self) -> String;
177
178 /// Get the link that exists under `Channel`.
179 fn link(&self) -> String;
180
181 /// Get the description that exists under `Channel`.
182 fn description(&self) -> String;
183
184 /// Get the optional language that exists under `Channel`.
185 fn language(&self) -> Option<String>;
186
187 /// Get the optional copyright that exists under `Channel`.
188 fn copyright(&self) -> Option<String>;
189
190 /// Get the optional managing editor that exists under `Channel`.
191 fn managing_editor(&self) -> Option<String>;
192
193 /// Get the optional web master that exists under `Channel`.
194 fn webmaster(&self) -> Option<String>;
195
196 /// Get the optional pub date that exists under `Channel`.
197 fn pub_date(&self) -> Option<String>;
198
199 /// Get the optional last build date that exists under `Channel`.
200 fn last_build_date(&self) -> Option<String>;
201
202 /// Get the categories that exists under `Channel`.
203 fn categories(&self) -> Vec<Category>;
204
205 /// Get the optional generator that exists under `Channel`.
206 fn generator(&self) -> Option<String>;
207
208 /// Get the optional docs that exists under `Channel`.
209 fn docs(&self) -> Option<String>;
210
211 /// Get the optional cloud that exists under `Channel`.
212 fn cloud(&self) -> Option<Cloud>;
213
214 /// Get the optional ttl that exists under `Channel`.
215 fn ttl(&self) -> Option<String>;
216
217 /// Get the optional image that exists under `Channel`.
218 fn image(&self) -> Option<Image>;
219
220 /// Get the optional text input that exists under `Channel`.
221 fn text_input(&self) -> Option<TextInput>;
222
223 /// Get the optional rating that exists under `Channel`.
224 fn rating(&self) -> Option<String>;
225
226 /// Get the skip hours that exists under `Channel`.
227 fn skip_hours(&self) -> Vec<String>;
228
229 /// Get the skip days that exists under `Channel`.
230 fn skip_days(&self) -> Vec<String>;
231
232 /// Get the items that exists under `Channel`.
233 fn items(&self) -> Vec<Item>;
234
235 /// Get the optional `ITunesChannelExtension` under `Channel`.
236 fn itunes_ext(&self) -> Option<ITunesChannelExtension>;
237}
238
239
240/// This `ChannelBuilder` struct creates the `Channel`.
241#[derive(Clone, Default)]
242pub struct ChannelBuilder
243{
244 title: String,
245 link: String,
246 description: String,
247 language: Option<String>,
248 copyright: Option<String>,
249 managing_editor: Option<String>,
250 webmaster: Option<String>,
251 pub_date: Option<String>,
252 last_build_date: Option<String>,
253 categories: Vec<Category>,
254 generator: Option<String>,
255 docs: Option<String>,
256 cloud: Option<Cloud>,
257 ttl: Option<i64>,
258 image: Option<Image>,
259 rating: Option<String>,
260 text_input: Option<TextInput>,
261 skip_hours: Vec<i64>,
262 skip_days: Vec<String>,
263 items: Vec<Item>,
264 itunes_ext: Option<ITunesChannelExtension>,
265}
266
267
268/// The Getter functions for `Cloud`
269pub trait CloudGetters
270{
271 /// Get the domain that exists under `Cloud`.
272 fn domain(&self) -> String;
273
274 /// Get the port that exists under `Cloud`.
275 fn port(&self) -> String;
276
277 /// Get the path that exists under `Cloud`.
278 fn path(&self) -> String;
279
280 /// Get the register procedure that exists under `Cloud`.
281 fn register_procedure(&self) -> String;
282
283 /// Get the protocol that exists under `Cloud`.
284 fn protocol(&self) -> String;
285}
286
287
288/// This `CloudBuilder` struct creates the `Cloud`.
289#[derive(Clone, Default)]
290pub struct CloudBuilder
291{
292 domain: String,
293 port: i64,
294 path: String,
295 register_procedure: String,
296 protocol: String,
297}
298
299
300/// The Getter functions for `Enclosure`
301pub trait EnclosureGetters
302{
303 /// Get the url that exists under `Enclosure`.
304 fn url(&self) -> String;
305
306 /// Get the length that exists under `Enclosure`.
307 fn length(&self) -> String;
308
309 /// Get the enclosure type that exists under `Enclosure`.
310 fn mime_type(&self) -> String;
311}
312
313
314/// This `EnclosureBuilder` struct creates the `Enclosure`.
315#[derive(Clone, Default)]
316pub struct EnclosureBuilder
317{
318 url: String,
319 length: i64,
320 mime_type: String,
321}
322
323
324/// The Getter functions for `Guid`
325pub trait GuidGetters
326{
327 /// Get the permalink that exists under `Guid`.
328 fn is_permalink(&self) -> bool;
329
330 /// Get the guid that exists under `Guid`.
331 fn value(&self) -> String;
332}
333
334
335/// This `GuidBuilder` struct creates the `Guid`.
336#[derive(Clone, Default)]
337pub struct GuidBuilder
338{
339 is_permalink: Option<bool>,
340 value: String,
341}
342
343
344/// The Getter functions for `Image`
345pub trait ImageGetters
346{
347 /// Get the url that exists under `Image`.
348 fn url(&self) -> String;
349
350 /// Get the title that exists under `Image`.
351 fn title(&self) -> String;
352
353 /// Get the link that exists under `Image`.
354 fn link(&self) -> String;
355
356 /// Get the width that exists under `Image`.
357 fn width(&self) -> Option<String>;
358
359 /// Get the height that exists under `Image`.
360 fn height(&self) -> Option<String>;
361
362 /// Get the description that exists under `Image`.
363 fn description(&self) -> Option<String>;
364}
365
366
367/// This `ImageBuilder` struct creates the `Image`.
368#[derive(Clone, Default)]
369pub struct ImageBuilder
370{
371 url: String,
372 title: String,
373 link: String,
374 width: Option<i64>,
375 height: Option<i64>,
376 description: Option<String>,
377}
378
379
380/// The Getter functions for `Item`
381pub trait ItemGetters
382{
383 /// Get the optional title that exists under `Item`.
384 fn title(&self) -> Option<String>;
385
386 /// Get the optional link that exists under `Item`.
387 fn link(&self) -> Option<String>;
388
389 /// Get the optional description that exists under `Item`.
390 fn description(&self) -> Option<String>;
391
392 /// Get the optional author that exists under `Item`.
393 fn author(&self) -> Option<String>;
394
395 /// Get the categories that exists under `Item`.
396 fn categories(&self) -> Vec<Category>;
397
398 /// Get the optional comments that exists under `Item`.
399 fn comments(&self) -> Option<String>;
400
401 /// Get the optional enclosure that exists under `Item`.
402 fn enclosure(&self) -> Option<Enclosure>;
403
404 /// Get the optional guid that exists under `Item`.
405 fn guid(&self) -> Option<Guid>;
406
407 /// Get the optional pub date that exists under `Item`.
408 fn pub_date(&self) -> Option<String>;
409
410 /// Get the optional source that exists under `Item`.
411 fn source(&self) -> Option<Source>;
412
413 /// Get the optional `ITunesItemExtension` under `Item`.
414 fn itunes_ext(&self) -> Option<ITunesItemExtension>;
415}
416
417
418/// This `ItemBuilder` struct creates the `Item`.
419#[derive(Clone, Default)]
420pub struct ItemBuilder
421{
422 title: Option<String>,
423 link: Option<String>,
424 description: Option<String>,
425 author: Option<String>,
426 categories: Vec<Category>,
427 comments: Option<String>,
428 enclosure: Option<Enclosure>,
429 guid: Option<Guid>,
430 pub_date: Option<String>,
431 source: Option<Source>,
432 itunes_ext: Option<ITunesItemExtension>,
433}
434
435
436/// The Getter functions for `Source`
437pub trait SourceGetters
438{
439 /// Get the url that exists under `Source`.
440 fn url(&self) -> String;
441
442 /// Get the source that exists under `Source`.
443 fn title(&self) -> Option<String>;
444}
445
446
447/// This `SourceBuilder` struct creates the `Source`.
448#[derive(Clone, Default)]
449pub struct SourceBuilder
450{
451 url: String,
452 title: Option<String>,
453}
454
455
456/// The Getter functions for `TextInput`
457pub trait TextInputGetters
458{
459 /// Get the title that exists under `TextInput`.
460 fn title(&self) -> String;
461
462 /// Get the description that exists under `TextInput`.
463 fn description(&self) -> String;
464
465 /// Get the name that exists under `TextInput`.
466 fn name(&self) -> String;
467
468 /// Get the link that exists under `TextInput`.
469 fn link(&self) -> String;
470}
471
472
473/// This `TextInputBuilder` struct creates the `TextInput`.
474#[derive(Clone, Default)]
475pub struct TextInputBuilder
476{
477 title: String,
478 description: String,
479 name: String,
480 link: String,
481}