~ubuntu-branches/debian/squeeze/f-spot/squeeze

« back to all changes in this revision

Viewing changes to extensions/Exporters/FlickrExport/FlickrNet/Flickr.cs

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane, Mirco Bauer, Iain Lane
  • Date: 2009-02-07 20:23:32 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: james.westby@ubuntu.com-20090207202332-oc93rfjo1st0571s
Tags: 0.5.0.3-2
[ Mirco Bauer]
* Upload to unstable.
* debian/control:
  + Lowered GNOME# build-deps to 2.0 ABI as that transition didn't happen
    yet in unstable.

[ Iain Lane ]
* debian/patches/svn-r4545_locales-import.dpatch: Patch backported from SVN
  trunk revision 4545 - initialize the translation catalog earlier (LP: #293305)
  (Closes: #514457). Thanks to Florian Heinle for finding the patch and to
  Chris Coulson for preparing the update.
* debian/control: Build-depend on libmono-dev (>= 1.2.4) to match configure
  checks.
* debian/rules: Pass CSC=/usr/bin/csc to configure for gio-sharp to fix FTBFS

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
using System;
 
2
using System.Net;
 
3
using System.IO;
 
4
using System.Xml;
 
5
using System.Xml.XPath;
 
6
using System.Xml.Serialization;
 
7
using System.Text;
 
8
using System.Collections;
 
9
using System.Collections.Specialized;
 
10
 
 
11
namespace FlickrNet
 
12
{
 
13
        /// <summary>
 
14
        /// The main Flickr class.
 
15
        /// </summary>
 
16
        /// <remarks>
 
17
        /// Create an instance of this class and then call its methods to perform methods on Flickr.
 
18
        /// </remarks>
 
19
        /// <example>
 
20
        /// <code>FlickrNet.Flickr flickr = new FlickrNet.Flickr();
 
21
        /// User user = flickr.PeopleFindByEmail("cal@iamcal.com");
 
22
        /// Console.WriteLine("User Id is " + u.UserId);</code>
 
23
        /// </example>
 
24
        //[System.Net.WebPermission(System.Security.Permissions.SecurityAction.Demand, ConnectPattern="http://www.flickr.com/.*")]
 
25
        public class Flickr
 
26
        {
 
27
 
 
28
                #region [ Upload Event and Delegate ]
 
29
                /// <summary>
 
30
                ///
 
31
                /// </summary>
 
32
                public delegate void UploadProgressHandler(object sender, UploadProgressEventArgs e);
 
33
 
 
34
                /// <summary>
 
35
                /// UploadProgressHandler is fired during a synchronous upload process to signify that
 
36
                /// a segment of uploading has been completed. This is approximately 50 bytes. The total
 
37
                /// uploaded is recorded in the <see cref="UploadProgressEventArgs"/> class.
 
38
                /// </summary>
 
39
                public event UploadProgressHandler OnUploadProgress;
 
40
                #endregion
 
41
 
 
42
                #region [ Private Variables ]
 
43
#if !WindowsCE
 
44
                private static bool _isServiceSet = false;
 
45
#endif
 
46
                private static SupportedService _defaultService = SupportedService.Flickr;
 
47
 
 
48
                private SupportedService _service = SupportedService.Flickr;
 
49
 
 
50
                private string BaseUrl
 
51
                {
 
52
                        get { return _baseUrl[(int)_service]; }
 
53
                }
 
54
 
 
55
                private string[] _baseUrl = new string[] {
 
56
                                                                                                                        "http://api.flickr.com/services/rest/",
 
57
                                                                                                                        "http://www.zooomr.com/api/rest/",
 
58
                                                                                                                        "http://www.23hq.com/services/rest/"};
 
59
 
 
60
                private string UploadUrl
 
61
                {
 
62
                        get { return _uploadUrl[(int)_service]; }
 
63
                }
 
64
                private static string[] _uploadUrl = new string[] {
 
65
                                                                                                                          "http://api.flickr.com/services/upload/",
 
66
                                                                                                                          "http://www.zooomr.com/api/upload",
 
67
                                                                                                                          "http://www.23hq.com/services/upload/"};
 
68
 
 
69
                private string ReplaceUrl
 
70
                {
 
71
                        get { return _replaceUrl[(int)_service]; }
 
72
                }
 
73
                private static string[] _replaceUrl = new string[] {
 
74
                                                                                                                           "http://api.flickr.com/services/replace/",
 
75
                                                                                                                           "http://www.zooomr.com/api/replace",
 
76
                                                                                                                           "http://www.23hq.com/services/replace/"};
 
77
 
 
78
                private string AuthUrl
 
79
                {
 
80
                        get { return _authUrl[(int)_service]; }
 
81
                }
 
82
                private static string[] _authUrl = new string[] {
 
83
                                                                                                                           "http://www.flickr.com/services/auth/",
 
84
                                                                                                                           "http://www.zooomr.com/services/auth/",
 
85
                                                                                                                           "http://www.23hq.com/services/auth/"};
 
86
 
 
87
                private string _apiKey;
 
88
                private string _apiToken;
 
89
                private string _sharedSecret;
 
90
                private int _timeout = 30000;
 
91
                private const string UserAgent = "Mozilla/4.0 FlickrNet API (compatible; MSIE 6.0; Windows NT 5.1)";
 
92
                private string _lastRequest;
 
93
                private string _lastResponse;
 
94
 
 
95
                private WebProxy _proxy;// = WebProxy.GetDefaultProxy();
 
96
 
 
97
                // Static serializers
 
98
                private static XmlSerializer _responseSerializer = new XmlSerializer(typeof(FlickrNet.Response));
 
99
                private static XmlSerializer _uploaderSerializer = new XmlSerializer(typeof(FlickrNet.Uploader));
 
100
 
 
101
                #endregion
 
102
 
 
103
                #region [ Public Properties ]
 
104
                /// <summary>
 
105
                /// Get or set the API Key to be used by all calls. API key is mandatory for all
 
106
                /// calls to Flickr.
 
107
                /// </summary>
 
108
                public string ApiKey
 
109
                {
 
110
                        get { return _apiKey; }
 
111
                        set { _apiKey = (value==null||value.Length==0?null:value); }
 
112
                }
 
113
 
 
114
                /// <summary>
 
115
                /// API shared secret is required for all calls that require signing, which includes
 
116
                /// all methods that require authentication, as well as the actual flickr.auth.* calls.
 
117
                /// </summary>
 
118
                public string ApiSecret
 
119
                {
 
120
                        get { return _sharedSecret; }
 
121
                        set { _sharedSecret = (value==null||value.Length==0?null:value); }
 
122
                }
 
123
 
 
124
                /// <summary>
 
125
                /// The API token is required for all calls that require authentication.
 
126
                /// A <see cref="FlickrException"/> will be raised by Flickr if the API token is
 
127
                /// not set when required.
 
128
                /// </summary>
 
129
                /// <remarks>
 
130
                /// It should be noted that some methods will work without the API token, but
 
131
                /// will return different results if used with them (such as group pool requests,
 
132
                /// and results which include private pictures the authenticated user is allowed to see
 
133
                /// (their own, or others).
 
134
                /// </remarks>
 
135
                [Obsolete("Renamed to AuthToken to be more consistent with the Flickr API")]
 
136
                public string ApiToken
 
137
                {
 
138
                        get { return _apiToken; }
 
139
                        set { _apiToken = (value==null||value.Length==0?null:value); }
 
140
                }
 
141
 
 
142
                /// <summary>
 
143
                /// The authentication token is required for all calls that require authentication.
 
144
                /// A <see cref="FlickrException"/> will be raised by Flickr if the authentication token is
 
145
                /// not set when required.
 
146
                /// </summary>
 
147
                /// <remarks>
 
148
                /// It should be noted that some methods will work without the authentication token, but
 
149
                /// will return different results if used with them (such as group pool requests,
 
150
                /// and results which include private pictures the authenticated user is allowed to see
 
151
                /// (their own, or others).
 
152
                /// </remarks>
 
153
                public string AuthToken
 
154
                {
 
155
                        get { return _apiToken; }
 
156
                        set { _apiToken = (value==null||value.Length==0?null:value); }
 
157
                }
 
158
 
 
159
                /// <summary>
 
160
                /// Gets or sets whether the cache should be disabled. Use only in extreme cases where you are sure you
 
161
                /// don't want any caching.
 
162
                /// </summary>
 
163
                public static bool CacheDisabled
 
164
                {
 
165
                        get { return Cache.CacheDisabled; }
 
166
                        set { Cache.CacheDisabled = value; }
 
167
                }
 
168
 
 
169
                /// <summary>
 
170
                /// All GET calls to Flickr are cached by the Flickr.Net API. Set the <see cref="CacheTimeout"/>
 
171
                /// to determine how long these calls should be cached (make this as long as possible!)
 
172
                /// </summary>
 
173
                public static TimeSpan CacheTimeout
 
174
                {
 
175
                        get { return Cache.CacheTimeout; }
 
176
                        set { Cache.CacheTimeout = value; }
 
177
                }
 
178
 
 
179
                /// <summary>
 
180
                /// Sets or gets the location to store the Cache files.
 
181
                /// </summary>
 
182
                public static string CacheLocation
 
183
                {
 
184
                        get { return Cache.CacheLocation; }
 
185
                        set { Cache.CacheLocation = value; }
 
186
                }
 
187
 
 
188
                /// <summary>
 
189
                /// Gets the current size of the Cache.
 
190
                /// </summary>
 
191
                public static long CacheSize
 
192
                {
 
193
                        get { return Cache.CacheSize; }
 
194
                }
 
195
 
 
196
                /// <summary>
 
197
                /// <see cref="CacheSizeLimit"/> is the cache file size in bytes for downloaded
 
198
                /// pictures. The default is 50MB (or 50 * 1024 * 1025 in bytes).
 
199
                /// </summary>
 
200
                public static long CacheSizeLimit
 
201
                {
 
202
                        get { return Cache.CacheSizeLimit; }
 
203
                        set { Cache.CacheSizeLimit = value; }
 
204
                }
 
205
 
 
206
                /// <summary>
 
207
                /// The default service to use for new Flickr instances
 
208
                /// </summary>
 
209
                public static SupportedService DefaultService
 
210
                {
 
211
                        get
 
212
                        {
 
213
#if !WindowsCE
 
214
                                if( !_isServiceSet && FlickrConfigurationManager.Settings != null )
 
215
                                {
 
216
                                        _defaultService = FlickrConfigurationManager.Settings.Service;
 
217
                                        _isServiceSet = true;
 
218
                                }
 
219
#endif
 
220
                return _defaultService;
 
221
                        }
 
222
                        set
 
223
                        {
 
224
                                _defaultService = value;
 
225
#if !WindowsCE
 
226
                                _isServiceSet = true;
 
227
#endif
 
228
                        }
 
229
                }
 
230
 
 
231
                /// <summary>
 
232
                /// The current service that the Flickr API is using.
 
233
                /// </summary>
 
234
                public SupportedService CurrentService
 
235
                {
 
236
                        get
 
237
                        {
 
238
                                return _service;
 
239
                        }
 
240
                        set
 
241
                        {
 
242
                                _service = value;
 
243
#if !WindowsCE
 
244
                                if( _service == SupportedService.Zooomr ) ServicePointManager.Expect100Continue = false;
 
245
#endif
 
246
                        }
 
247
                }
 
248
 
 
249
                /// <summary>
 
250
                /// Internal timeout for all web requests in milliseconds. Defaults to 30 seconds.
 
251
                /// </summary>
 
252
                public int HttpTimeout
 
253
                {
 
254
                        get { return _timeout; }
 
255
                        set { _timeout = value; }
 
256
                }
 
257
 
 
258
                /// <summary>
 
259
                /// Checks to see if a shared secret and an api token are stored in the object.
 
260
                /// Does not check if these values are valid values.
 
261
                /// </summary>
 
262
                public bool IsAuthenticated
 
263
                {
 
264
                        get { return (_sharedSecret != null && _apiToken != null); }
 
265
                }
 
266
 
 
267
                /// <summary>
 
268
                /// Returns the raw XML returned from the last response.
 
269
                /// Only set it the response was not returned from cache.
 
270
                /// </summary>
 
271
                public string LastResponse
 
272
                {
 
273
                        get { return _lastResponse; }
 
274
                }
 
275
 
 
276
                /// <summary>
 
277
                /// Returns the last URL requested. Includes API signing.
 
278
                /// </summary>
 
279
                public string LastRequest
 
280
                {
 
281
                        get { return _lastRequest; }
 
282
                }
 
283
 
 
284
                /// <summary>
 
285
                /// You can set the <see cref="WebProxy"/> or alter its properties.
 
286
                /// It defaults to your internet explorer proxy settings.
 
287
                /// </summary>
 
288
                public WebProxy Proxy { get { return _proxy; } set { _proxy = value; } }
 
289
                #endregion
 
290
 
 
291
                #region [ Cache Methods ]
 
292
                /// <summary>
 
293
                /// Clears the cache completely.
 
294
                /// </summary>
 
295
                public static void FlushCache()
 
296
                {
 
297
                        Cache.FlushCache();
 
298
                }
 
299
 
 
300
                /// <summary>
 
301
                /// Clears the cache for a particular URL.
 
302
                /// </summary>
 
303
                /// <param name="url">The URL to remove from the cache.</param>
 
304
                /// <remarks>
 
305
                /// The URL can either be an image URL for a downloaded picture, or
 
306
                /// a request URL (see <see cref="LastRequest"/> for getting the last URL).
 
307
                /// </remarks>
 
308
                public static void FlushCache(string url)
 
309
                {
 
310
                        Cache.FlushCache(url);
 
311
                }
 
312
 
 
313
                /// <summary>
 
314
                /// Provides static access to the list of cached photos.
 
315
                /// </summary>
 
316
                /// <returns>An array of <see cref="PictureCacheItem"/> objects.</returns>
 
317
                public static PictureCacheItem[] GetCachePictures()
 
318
                {
 
319
                        return (PictureCacheItem[]) Cache.Downloads.ToArray(typeof(PictureCacheItem));
 
320
                }
 
321
                #endregion
 
322
 
 
323
                #region [ Constructors ]
 
324
 
 
325
                /// <summary>
 
326
                /// Constructor loads configuration settings from app.config or web.config file if they exist.
 
327
                /// </summary>
 
328
                public Flickr()
 
329
        {
 
330
#if !WindowsCE
 
331
            FlickrConfigurationSettings settings = FlickrConfigurationManager.Settings;
 
332
                        if( settings == null ) return;
 
333
 
 
334
                        if( settings.CacheSize != 0 ) CacheSizeLimit = settings.CacheSize;
 
335
                        if( settings.CacheTimeout != TimeSpan.MinValue ) CacheTimeout = settings.CacheTimeout;
 
336
                        ApiKey = settings.ApiKey;
 
337
                        AuthToken = settings.ApiToken;
 
338
                        ApiSecret = settings.SharedSecret;
 
339
 
 
340
            if (settings.IsProxyDefined)
 
341
                        {
 
342
                                Proxy = new WebProxy();
 
343
                                Proxy.Address = new Uri("http://" + settings.ProxyIPAddress + ":" + settings.ProxyPort);
 
344
                                if( settings.ProxyUsername != null && settings.ProxyUsername.Length > 0 )
 
345
                                {
 
346
                                        NetworkCredential creds = new NetworkCredential();
 
347
                                        creds.UserName = settings.ProxyUsername;
 
348
                                        creds.Password = settings.ProxyPassword;
 
349
                                        creds.Domain = settings.ProxyDomain;
 
350
                                        Proxy.Credentials = creds;
 
351
                                }
 
352
                        }
 
353
                        else
 
354
                        {
 
355
                                // try and get default IE settings
 
356
                                try
 
357
                                {
 
358
                                        Proxy = WebProxy.GetDefaultProxy();
 
359
                                }
 
360
                                catch(System.Security.SecurityException)
 
361
                                {
 
362
                                        // Capture SecurityException for when running in a Medium Trust environment.
 
363
                                }
 
364
                        }
 
365
 
 
366
#endif
 
367
 
 
368
            CurrentService = DefaultService;
 
369
                }
 
370
 
 
371
                /// <summary>
 
372
                /// Create a new instance of the <see cref="Flickr"/> class with no authentication.
 
373
                /// </summary>
 
374
                /// <param name="apiKey">Your Flickr API Key.</param>
 
375
                public Flickr(string apiKey) : this(apiKey, "", "")
 
376
                {
 
377
                }
 
378
 
 
379
                /// <summary>
 
380
                /// Creates a new instance of the <see cref="Flickr"/> class with an API key and a Shared Secret.
 
381
                /// This is only useful really useful for calling the Auth functions as all other
 
382
                /// authenticationed methods also require the API Token.
 
383
                /// </summary>
 
384
                /// <param name="apiKey">Your Flickr API Key.</param>
 
385
                /// <param name="sharedSecret">Your Flickr Shared Secret.</param>
 
386
                public Flickr(string apiKey, string sharedSecret) : this(apiKey, sharedSecret, "")
 
387
                {
 
388
                }
 
389
 
 
390
                /// <summary>
 
391
                /// Create a new instance of the <see cref="Flickr"/> class with the email address and password given
 
392
                /// </summary>
 
393
                /// <param name="apiKey">Your Flickr API Key</param>
 
394
                /// <param name="sharedSecret">Your FLickr Shared Secret.</param>
 
395
                /// <param name="token">The token for the user who has been authenticated.</param>
 
396
                public Flickr(string apiKey, string sharedSecret, string token) : this()
 
397
                {
 
398
                        _apiKey = apiKey;
 
399
                        _sharedSecret = sharedSecret;
 
400
                        _apiToken = token;
 
401
                }
 
402
                #endregion
 
403
 
 
404
                #region [ Private Methods ]
 
405
                /// <summary>
 
406
                /// A private method which performs the actual HTTP web request if
 
407
                /// the details are not found within the cache.
 
408
                /// </summary>
 
409
                /// <param name="url">The URL to download.</param>
 
410
                /// <param name="variables">The query string parameters to be added to the end of the URL.</param>
 
411
                /// <returns>A <see cref="FlickrNet.Response"/> object.</returns>
 
412
                /// <remarks>If the final length of the URL would be greater than 2000 characters
 
413
                /// then they are sent as part of the body instead.</remarks>
 
414
                private string DoGetResponse(string url, string variables)
 
415
                {
 
416
                        HttpWebRequest req = null;
 
417
                        HttpWebResponse res = null;
 
418
 
 
419
                        if( variables.Length < 2000 )
 
420
                        {
 
421
                                url += "?" + variables;
 
422
                                variables = "";
 
423
                        }
 
424
 
 
425
                        // Initialise the web request
 
426
                        req = (HttpWebRequest)HttpWebRequest.Create(url);
 
427
                        req.Method = CurrentService==SupportedService.Zooomr?"GET":"POST";
 
428
 
 
429
            if (req.Method == "POST") req.ContentLength = variables.Length;
 
430
 
 
431
            req.UserAgent = UserAgent;
 
432
                        if( Proxy != null ) req.Proxy = Proxy;
 
433
                        req.Timeout = HttpTimeout;
 
434
                        req.KeepAlive = false;
 
435
            if (variables.Length > 0)
 
436
            {
 
437
                req.ContentType = "application/x-www-form-urlencoded";
 
438
                StreamWriter sw = new StreamWriter(req.GetRequestStream());
 
439
                sw.Write(variables);
 
440
                sw.Close();
 
441
            }
 
442
            else
 
443
            {
 
444
                // This is needed in the Compact Framework
 
445
                // See for more details: http://msdn2.microsoft.com/en-us/library/1afx2b0f.aspx
 
446
                if (req.Method=="POST")
 
447
                        req.GetRequestStream().Close();
 
448
            }
 
449
 
 
450
                        try
 
451
                        {
 
452
                                // Get response from the internet
 
453
                                res = (HttpWebResponse)req.GetResponse();
 
454
                        }
 
455
                        catch(WebException ex)
 
456
                        {
 
457
                                if( ex.Status == WebExceptionStatus.ProtocolError )
 
458
                                {
 
459
                                        HttpWebResponse res2 = (HttpWebResponse)ex.Response;
 
460
                                        if( res2 != null )
 
461
                                        {
 
462
                                                throw new FlickrWebException(String.Format("HTTP Error {0}, {1}", (int)res2.StatusCode, res2.StatusDescription), ex);
 
463
                                        }
 
464
                                }
 
465
                                throw new FlickrWebException(ex.Message, ex);
 
466
                        }
 
467
 
 
468
                        string responseString = string.Empty;
 
469
 
 
470
                        using (StreamReader sr = new StreamReader(res.GetResponseStream()))
 
471
                        {
 
472
                                responseString = sr.ReadToEnd();
 
473
                        }
 
474
 
 
475
                        return responseString;
 
476
                }
 
477
 
 
478
                /// <summary>
 
479
                /// Download a picture (or anything else actually).
 
480
                /// </summary>
 
481
                /// <param name="url"></param>
 
482
                /// <returns></returns>
 
483
                private Stream DoDownloadPicture(string url)
 
484
                {
 
485
                        HttpWebRequest req = null;
 
486
                        HttpWebResponse res = null;
 
487
 
 
488
                        try
 
489
                        {
 
490
                                req = (HttpWebRequest)HttpWebRequest.Create(url);
 
491
                                req.UserAgent = UserAgent;
 
492
                                if( Proxy != null ) req.Proxy = Proxy;
 
493
                                req.Timeout = HttpTimeout;
 
494
                                req.KeepAlive = false;
 
495
                                res = (HttpWebResponse)req.GetResponse();
 
496
                        }
 
497
                        catch(WebException ex)
 
498
                        {
 
499
                                if( ex.Status == WebExceptionStatus.ProtocolError )
 
500
                                {
 
501
                                        HttpWebResponse res2 = (HttpWebResponse)ex.Response;
 
502
                                        if( res2 != null )
 
503
                                        {
 
504
                                                throw new FlickrWebException(String.Format("HTTP Error while downloading photo: {0}, {1}", (int)res2.StatusCode, res2.StatusDescription), ex);
 
505
                                        }
 
506
                                }
 
507
                                else if( ex.Status == WebExceptionStatus.Timeout )
 
508
                                {
 
509
                                        throw new FlickrWebException("The request timed-out", ex);
 
510
                                }
 
511
                                throw new FlickrWebException("Picture download failed (" + ex.Message + ")", ex);
 
512
                        }
 
513
 
 
514
                        return res.GetResponseStream();
 
515
                }
 
516
                #endregion
 
517
 
 
518
                #region [ GetResponse methods ]
 
519
                private Response GetResponseNoCache(Hashtable parameters)
 
520
                {
 
521
                        return GetResponse(parameters, TimeSpan.MinValue);
 
522
                }
 
523
 
 
524
                private Response GetResponseAlwaysCache(Hashtable parameters)
 
525
                {
 
526
                        return GetResponse(parameters, TimeSpan.MaxValue);
 
527
                }
 
528
 
 
529
                private Response GetResponseCache(Hashtable parameters)
 
530
                {
 
531
                        return GetResponse(parameters, Cache.CacheTimeout);
 
532
                }
 
533
 
 
534
                private Response GetResponse(Hashtable parameters, TimeSpan cacheTimeout)
 
535
                {
 
536
                        CheckApiKey();
 
537
 
 
538
                        // Calulate URL
 
539
                        string url = BaseUrl;
 
540
 
 
541
            StringBuilder UrlStringBuilder = new StringBuilder("", 2 * 1024);
 
542
            StringBuilder HashStringBuilder = new StringBuilder(_sharedSecret, 2 * 1024);
 
543
 
 
544
                        parameters["api_key"] = _apiKey;
 
545
 
 
546
                        if( _apiToken != null && _apiToken.Length > 0 )
 
547
                        {
 
548
                                parameters["auth_token"] = _apiToken;
 
549
                        }
 
550
 
 
551
                        string[] keys = new string[parameters.Keys.Count];
 
552
                        parameters.Keys.CopyTo(keys, 0);
 
553
                        Array.Sort(keys);
 
554
 
 
555
                        foreach(string key in keys)
 
556
                        {
 
557
                                if( UrlStringBuilder.Length > 0 ) UrlStringBuilder.Append("&");
 
558
                UrlStringBuilder.Append(key);
 
559
                UrlStringBuilder.Append("=");
 
560
                UrlStringBuilder.Append(Utils.UrlEncode(Convert.ToString(parameters[key])));
 
561
                HashStringBuilder.Append(key);
 
562
                HashStringBuilder.Append(parameters[key]);
 
563
                        }
 
564
 
 
565
            if (_sharedSecret != null && _sharedSecret.Length > 0)
 
566
            {
 
567
                if (UrlStringBuilder.Length > BaseUrl.Length + 1)
 
568
                {
 
569
                    UrlStringBuilder.Append("&");
 
570
                }
 
571
                UrlStringBuilder.Append("api_sig=");
 
572
                UrlStringBuilder.Append(Md5Hash(HashStringBuilder.ToString()));
 
573
            }
 
574
 
 
575
                        string variables = UrlStringBuilder.ToString();
 
576
                        _lastRequest = url;
 
577
                        _lastResponse = string.Empty;
 
578
 
 
579
                        if( CacheDisabled )
 
580
                        {
 
581
                                string responseXml = DoGetResponse(url, variables);
 
582
                                _lastResponse = responseXml;
 
583
                                return Utils.Deserialize(responseXml);
 
584
                        }
 
585
                        else
 
586
                        {
 
587
                                ResponseCacheItem cached = (ResponseCacheItem) Cache.Responses.Get(url + "?" + variables, cacheTimeout, true);
 
588
                                if (cached != null)
 
589
                                {
 
590
                                        System.Diagnostics.Debug.WriteLine("Cache hit");
 
591
                                        _lastResponse = cached.Response;
 
592
                                        return Utils.Deserialize(cached.Response);
 
593
                                }
 
594
                                else
 
595
                                {
 
596
                                        System.Diagnostics.Debug.WriteLine("Cache miss");
 
597
                                        string responseXml = DoGetResponse(url, variables);
 
598
                                        _lastResponse = responseXml;
 
599
 
 
600
                                        ResponseCacheItem resCache = new ResponseCacheItem();
 
601
                                        resCache.Response = responseXml;
 
602
                                        resCache.Url = url;
 
603
                                        resCache.CreationTime = DateTime.UtcNow;
 
604
 
 
605
                                        FlickrNet.Response response = Utils.Deserialize(responseXml);
 
606
 
 
607
                                        if( response.Status == ResponseStatus.OK )
 
608
                                        {
 
609
                                                Cache.Responses.Shrink(Math.Max(0, Cache.CacheSizeLimit - responseXml.Length));
 
610
                                                Cache.Responses[url] = resCache;
 
611
                                        }
 
612
 
 
613
                                        return response;
 
614
                                }
 
615
                        }
 
616
                }
 
617
 
 
618
                #endregion
 
619
 
 
620
                #region [ DownloadPicture ]
 
621
                /// <summary>
 
622
                /// Downloads the picture from a internet and transfers it to a stream object.
 
623
                /// </summary>
 
624
                /// <param name="url">The url of the image to download.</param>
 
625
                /// <returns>A <see cref="Stream"/> object containing the downloaded picture.</returns>
 
626
                /// <remarks>
 
627
                /// The method checks the download cache first to see if the picture has already
 
628
                /// been downloaded and if so returns the cached image. Otherwise it goes to the internet for the actual
 
629
                /// image.
 
630
                /// </remarks>
 
631
                public System.IO.Stream DownloadPicture(string url)
 
632
                {
 
633
                        if( CacheDisabled )
 
634
                        {
 
635
                                return DoDownloadPicture(url);
 
636
                        }
 
637
 
 
638
                        const int BUFFER_SIZE = 1024 * 10;
 
639
 
 
640
                        PictureCacheItem cacheItem = (PictureCacheItem) Cache.Downloads[url];
 
641
                        if (cacheItem != null)
 
642
                        {
 
643
                                return  new FileStream(cacheItem.filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 
644
                        }
 
645
 
 
646
                        PictureCacheItem picCache = new PictureCacheItem();
 
647
                        picCache.filename = Path.Combine(Cache.CacheLocation,Guid.NewGuid().ToString());
 
648
                        Stream read = DoDownloadPicture(url);
 
649
                        Stream write = new FileStream(picCache.filename, FileMode.Create, FileAccess.Write, FileShare.None);
 
650
 
 
651
                        byte[] buffer = new byte[BUFFER_SIZE];
 
652
                        int bytes = 0;
 
653
                        long fileSize = 0;
 
654
 
 
655
                        while( (bytes = read.Read(buffer, 0, BUFFER_SIZE)) > 0 )
 
656
                        {
 
657
                                fileSize += bytes;
 
658
                                write.Write(buffer, 0, bytes);
 
659
                        }
 
660
 
 
661
                        read.Close();
 
662
                        write.Close();
 
663
 
 
664
                        picCache.url = url;
 
665
                        picCache.creationTime = DateTime.UtcNow;
 
666
                        picCache.fileSize = fileSize;
 
667
 
 
668
                        Cache.Downloads.Shrink(Math.Max(0, Cache.CacheSizeLimit - fileSize));
 
669
                        Cache.Downloads[url] = picCache;
 
670
 
 
671
                        return new FileStream(picCache.filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 
672
                }
 
673
                #endregion
 
674
 
 
675
                #region [ Auth ]
 
676
                /// <summary>
 
677
                /// Retrieve a temporary FROB from the Flickr service, to be used in redirecting the
 
678
                /// user to the Flickr web site for authentication. Only required for desktop authentication.
 
679
                /// </summary>
 
680
                /// <remarks>
 
681
                /// Pass the FROB to the <see cref="AuthCalcUrl"/> method to calculate the url.
 
682
                /// </remarks>
 
683
                /// <example>
 
684
                /// <code>
 
685
                /// string frob = flickr.AuthGetFrob();
 
686
                /// string url = flickr.AuthCalcUrl(frob, AuthLevel.Read);
 
687
                ///
 
688
                /// // redirect the user to the url above and then wait till they have authenticated and return to the app.
 
689
                ///
 
690
                /// Auth auth = flickr.AuthGetToken(frob);
 
691
                ///
 
692
                /// // then store the auth.Token for later use.
 
693
                /// string token = auth.Token;
 
694
                /// </code>
 
695
                /// </example>
 
696
                /// <returns>The FROB.</returns>
 
697
                public string AuthGetFrob()
 
698
                {
 
699
                        Hashtable parameters = new Hashtable();
 
700
                        parameters.Add("method", "flickr.auth.getFrob");
 
701
 
 
702
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
703
                        if( response.Status == ResponseStatus.OK )
 
704
                        {
 
705
                                return response.AllElements[CurrentService==SupportedService.Zooomr?1:0].InnerText;
 
706
                        }
 
707
                        else
 
708
                        {
 
709
                                throw new FlickrApiException(response.Error);
 
710
                        }
 
711
                }
 
712
 
 
713
                /// <summary>
 
714
                /// Calculates the URL to redirect the user to Flickr web site for
 
715
                /// authentication. Used by desktop application.
 
716
                /// See <see cref="AuthGetFrob"/> for example code.
 
717
                /// </summary>
 
718
                /// <param name="frob">The FROB to be used for authentication.</param>
 
719
                /// <param name="authLevel">The <see cref="AuthLevel"/> stating the maximum authentication level your application requires.</param>
 
720
                /// <returns>The url to redirect the user to.</returns>
 
721
                public string AuthCalcUrl(string frob, AuthLevel authLevel)
 
722
                {
 
723
                        if( _sharedSecret == null ) throw new SignatureRequiredException();
 
724
 
 
725
                        string hash = _sharedSecret + "api_key" + _apiKey + "frob" + frob + "perms" + authLevel.ToString().ToLower();
 
726
                        hash = Md5Hash(hash);
 
727
                        string url = AuthUrl + "?api_key=" + _apiKey + "&perms=" + authLevel.ToString().ToLower() + "&frob=" + frob;
 
728
                        url += "&api_sig=" + hash;
 
729
 
 
730
                        return url;
 
731
                }
 
732
 
 
733
                /// <summary>
 
734
                /// Calculates the URL to redirect the user to Flickr web site for
 
735
                /// auehtntication. Used by Web applications.
 
736
                /// See <see cref="AuthGetFrob"/> for example code.
 
737
                /// </summary>
 
738
                /// <remarks>
 
739
                /// The Flickr web site provides 'tiny urls' that can be used in place
 
740
                /// of this URL when you specify your return url in the API key page.
 
741
                /// It is recommended that you use these instead as they do not include
 
742
                /// your API or shared secret.
 
743
                /// </remarks>
 
744
                /// <param name="authLevel">The <see cref="AuthLevel"/> stating the maximum authentication level your application requires.</param>
 
745
                /// <returns>The url to redirect the user to.</returns>
 
746
                public string AuthCalcWebUrl(AuthLevel authLevel)
 
747
                {
 
748
                        if( _sharedSecret == null ) throw new SignatureRequiredException();
 
749
 
 
750
                        string hash = _sharedSecret + "api_key" + _apiKey + "perms" + authLevel.ToString().ToLower();
 
751
                        hash = Md5Hash(hash);
 
752
                        string url = AuthUrl + "?api_key=" + _apiKey + "&perms=" + authLevel.ToString().ToLower();
 
753
                        url += "&api_sig=" + hash;
 
754
 
 
755
                        return url;
 
756
                }
 
757
 
 
758
                /// <summary>
 
759
                /// After the user has authenticated your application on the flickr web site call this
 
760
                /// method with the FROB (either stored from <see cref="AuthGetFrob"/> or returned in the URL
 
761
                /// from the Flickr web site) to get the users token.
 
762
                /// </summary>
 
763
                /// <param name="frob">The string containing the FROB.</param>
 
764
                /// <returns>A <see cref="Auth"/> object containing user and token details.</returns>
 
765
                public Auth AuthGetToken(string frob)
 
766
                {
 
767
                        if( _sharedSecret == null ) throw new SignatureRequiredException();
 
768
 
 
769
                        Hashtable parameters = new Hashtable();
 
770
                        parameters.Add("method", "flickr.auth.getToken");
 
771
                        parameters.Add("frob", frob);
 
772
 
 
773
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
774
                        if( response.Status == ResponseStatus.OK )
 
775
                        {
 
776
                                Auth auth = new Auth(response.AllElements[CurrentService==SupportedService.Zooomr?1:0]);
 
777
                                return auth;
 
778
                        }
 
779
                        else
 
780
                        {
 
781
                                throw new FlickrApiException(response.Error);
 
782
                        }
 
783
                }
 
784
 
 
785
                /// <summary>
 
786
                /// Gets the full token details for a given mini token, entered by the user following a
 
787
                /// web based authentication.
 
788
                /// </summary>
 
789
                /// <param name="miniToken">The mini token.</param>
 
790
                /// <returns>An instance <see cref="Auth"/> class, detailing the user and their full token.</returns>
 
791
                public Auth AuthGetFullToken(string miniToken)
 
792
                {
 
793
                        Hashtable parameters = new Hashtable();
 
794
                        parameters.Add("method", "flickr.auth.getFullToken");
 
795
                        parameters.Add("mini_token", miniToken.Replace("-", ""));
 
796
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
797
 
 
798
                        if( response.Status == ResponseStatus.OK )
 
799
                        {
 
800
                                Auth auth = new Auth(response.AllElements[0]);
 
801
                                return auth;
 
802
                        }
 
803
                        else
 
804
                        {
 
805
                                throw new FlickrApiException(response.Error);
 
806
                        }
 
807
                }
 
808
 
 
809
                /// <summary>
 
810
                /// Checks a authentication token with the flickr service to make
 
811
                /// sure it is still valid.
 
812
                /// </summary>
 
813
                /// <param name="token">The authentication token to check.</param>
 
814
                /// <returns>The <see cref="Auth"/> object detailing the user for the token.</returns>
 
815
                public Auth AuthCheckToken(string token)
 
816
                {
 
817
                        Hashtable parameters = new Hashtable();
 
818
                        parameters.Add("method", "flickr.auth.checkToken");
 
819
                        parameters.Add("auth_token", token);
 
820
 
 
821
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
822
                        if( response.Status == ResponseStatus.OK )
 
823
                        {
 
824
                                Auth auth = new Auth(response.AllElements[CurrentService==SupportedService.Zooomr?1:0]);
 
825
                                return auth;
 
826
                        }
 
827
                        else
 
828
                        {
 
829
                                throw new FlickrApiException(response.Error);
 
830
                        }
 
831
 
 
832
                }
 
833
                #endregion
 
834
 
 
835
                #region [ Activity ]
 
836
                /// <summary>
 
837
                /// Returns a list of recent activity on photos belonging to the calling user.
 
838
                /// </summary>
 
839
                /// <remarks>
 
840
                /// <b>Do not poll this method more than once an hour.</b>
 
841
                /// </remarks>
 
842
                /// <returns>An array of <see cref="ActivityItem"/> instances.</returns>
 
843
                public ActivityItem[] ActivityUserPhotos()
 
844
                {
 
845
                        return ActivityUserPhotos(null);
 
846
                }
 
847
 
 
848
                /// <summary>
 
849
                /// Returns a list of recent activity on photos belonging to the calling user.
 
850
                /// </summary>
 
851
                /// <remarks>
 
852
                /// <b>Do not poll this method more than once an hour.</b>
 
853
                /// </remarks>
 
854
                /// <param name="timePeriod">The number of days or hours you want to get activity for.</param>
 
855
                /// <param name="timeType">'d' for days, 'h' for hours.</param>
 
856
                /// <returns>An array of <see cref="ActivityItem"/> instances.</returns>
 
857
                public ActivityItem[] ActivityUserPhotos(int timePeriod, string timeType)
 
858
                {
 
859
                        if( timePeriod == 0 )
 
860
                                throw new ArgumentOutOfRangeException("timePeriod", "Time Period should be greater than 0");
 
861
 
 
862
                        if( timeType == null )
 
863
                                throw new ArgumentNullException("timeType");
 
864
 
 
865
                        if( timeType != "d" && timeType != "h" )
 
866
                                throw new ArgumentOutOfRangeException("timeType", "Time type must be 'd' or 'h'");
 
867
 
 
868
                        return ActivityUserPhotos(timePeriod + timeType);
 
869
                }
 
870
 
 
871
                private ActivityItem[] ActivityUserPhotos(string timeframe)
 
872
                {
 
873
                        Hashtable parameters = new Hashtable();
 
874
                        parameters.Add("method", "flickr.activity.userPhotos");
 
875
                        if( timeframe != null && timeframe.Length > 0 ) parameters.Add("timeframe", timeframe);
 
876
 
 
877
                        FlickrNet.Response response = GetResponseCache(parameters);
 
878
                        if( response.Status == ResponseStatus.OK )
 
879
                        {
 
880
                                XmlNodeList list = response.AllElements[0].SelectNodes("item");
 
881
                                ActivityItem[] items = new ActivityItem[list.Count];
 
882
                                for(int i = 0; i < items.Length; i++)
 
883
                                {
 
884
                                        items[i] = new ActivityItem(list[i]);
 
885
                                }
 
886
                                return items;
 
887
                        }
 
888
                        else
 
889
                        {
 
890
                                throw new FlickrApiException(response.Error);
 
891
                        }
 
892
                }
 
893
 
 
894
                /// <summary>
 
895
                /// Returns a list of recent activity on photos commented on by the calling user.
 
896
                /// </summary>
 
897
                /// <remarks>
 
898
                /// <b>Do not poll this method more than once an hour.</b>
 
899
                /// </remarks>
 
900
                /// <returns></returns>
 
901
                public ActivityItem[] ActivityUserComments(int page, int perPage)
 
902
                {
 
903
                        Hashtable parameters = new Hashtable();
 
904
                        parameters.Add("method", "flickr.activity.userComments");
 
905
                        if( page > 0 ) parameters.Add("page", page);
 
906
                        if( perPage > 0 ) parameters.Add("per_page", perPage);
 
907
 
 
908
                        FlickrNet.Response response = GetResponseCache(parameters);
 
909
                        if( response.Status == ResponseStatus.OK )
 
910
                        {
 
911
                                XmlNodeList list = response.AllElements[0].SelectNodes("item");
 
912
                                ActivityItem[] items = new ActivityItem[list.Count];
 
913
                                for(int i = 0; i < items.Length; i++)
 
914
                                {
 
915
                                        items[i] = new ActivityItem(list[i]);
 
916
                                }
 
917
                                return items;
 
918
                        }
 
919
                        else
 
920
                        {
 
921
                                throw new FlickrApiException(response.Error);
 
922
                        }
 
923
                }
 
924
                #endregion
 
925
 
 
926
                #region [ UploadPicture ]
 
927
                /// <summary>
 
928
                /// Uploads a file to Flickr.
 
929
                /// </summary>
 
930
                /// <param name="filename">The filename of the file to open.</param>
 
931
                /// <returns>The id of the photo on a successful upload.</returns>
 
932
                /// <exception cref="FlickrException">Thrown when Flickr returns an error. see http://www.flickr.com/services/api/upload.api.html for more details.</exception>
 
933
                /// <remarks>Other exceptions may be thrown, see <see cref="FileStream"/> constructors for more details.</remarks>
 
934
                public string UploadPicture(string filename)
 
935
                {
 
936
                        return UploadPicture(filename, null, null, null, true, false, false);
 
937
                }
 
938
 
 
939
                /// <summary>
 
940
                /// Uploads a file to Flickr.
 
941
                /// </summary>
 
942
                /// <param name="filename">The filename of the file to open.</param>
 
943
                /// <param name="title">The title of the photograph.</param>
 
944
                /// <returns>The id of the photo on a successful upload.</returns>
 
945
                /// <exception cref="FlickrException">Thrown when Flickr returns an error. see http://www.flickr.com/services/api/upload.api.html for more details.</exception>
 
946
                /// <remarks>Other exceptions may be thrown, see <see cref="FileStream"/> constructors for more details.</remarks>
 
947
                public string UploadPicture(string filename, string title)
 
948
                {
 
949
                        return UploadPicture(filename, title, null, null, true, false, false);
 
950
                }
 
951
 
 
952
                /// <summary>
 
953
                /// Uploads a file to Flickr.
 
954
                /// </summary>
 
955
                /// <param name="filename">The filename of the file to open.</param>
 
956
                /// <param name="title">The title of the photograph.</param>
 
957
                /// <param name="description">The description of the photograph.</param>
 
958
                /// <returns>The id of the photo on a successful upload.</returns>
 
959
                /// <exception cref="FlickrException">Thrown when Flickr returns an error. see http://www.flickr.com/services/api/upload.api.html for more details.</exception>
 
960
                /// <remarks>Other exceptions may be thrown, see <see cref="FileStream"/> constructors for more details.</remarks>
 
961
                public string UploadPicture(string filename, string title, string description)
 
962
                {
 
963
                        return UploadPicture(filename, title, description, null, true, false, false);
 
964
                }
 
965
 
 
966
                /// <summary>
 
967
                /// Uploads a file to Flickr.
 
968
                /// </summary>
 
969
                /// <param name="filename">The filename of the file to open.</param>
 
970
                /// <param name="title">The title of the photograph.</param>
 
971
                /// <param name="description">The description of the photograph.</param>
 
972
                /// <param name="tags">A comma seperated list of the tags to assign to the photograph.</param>
 
973
                /// <returns>The id of the photo on a successful upload.</returns>
 
974
                /// <exception cref="FlickrException">Thrown when Flickr returns an error. see http://www.flickr.com/services/api/upload.api.html for more details.</exception>
 
975
                /// <remarks>Other exceptions may be thrown, see <see cref="FileStream"/> constructors for more details.</remarks>
 
976
                public string UploadPicture(string filename, string title, string description, string tags)
 
977
                {
 
978
                        Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 
979
                        return UploadPicture(stream, title, description, tags, -1, -1, -1, ContentType.None, SafetyLevel.None, HiddenFromSearch.None);
 
980
                }
 
981
 
 
982
                /// <summary>
 
983
                /// Uploads a file to Flickr.
 
984
                /// </summary>
 
985
                /// <param name="filename">The filename of the file to open.</param>
 
986
                /// <param name="title">The title of the photograph.</param>
 
987
                /// <param name="description">The description of the photograph.</param>
 
988
                /// <param name="tags">A comma seperated list of the tags to assign to the photograph.</param>
 
989
                /// <param name="isPublic">True if the photograph should be public and false if it should be private.</param>
 
990
                /// <param name="isFriend">True if the photograph should be marked as viewable by friends contacts.</param>
 
991
                /// <param name="isFamily">True if the photograph should be marked as viewable by family contacts.</param>
 
992
                /// <returns>The id of the photo on a successful upload.</returns>
 
993
                /// <exception cref="FlickrException">Thrown when Flickr returns an error. see http://www.flickr.com/services/api/upload.api.html for more details.</exception>
 
994
                /// <remarks>Other exceptions may be thrown, see <see cref="FileStream"/> constructors for more details.</remarks>
 
995
                public string UploadPicture(string filename, string title, string description, string tags, bool isPublic, bool isFamily, bool isFriend)
 
996
                {
 
997
                        Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 
998
                        return UploadPicture(stream, title, description, tags, isPublic?1:0, isFamily?1:0, isFriend?1:0, ContentType.None, SafetyLevel.None, HiddenFromSearch.None);
 
999
                }
 
1000
 
 
1001
                /// <summary>
 
1002
                /// UploadPicture method that does all the uploading work.
 
1003
                /// </summary>
 
1004
                /// <param name="stream">The <see cref="Stream"/> object containing the pphoto to be uploaded.</param>
 
1005
                /// <param name="title">The title of the photo (optional).</param>
 
1006
                /// <param name="description">The description of the photograph (optional).</param>
 
1007
                /// <param name="tags">The tags for the photograph (optional).</param>
 
1008
                /// <param name="isPublic">0 for private, 1 for public.</param>
 
1009
                /// <param name="isFamily">1 if family, 0 is not.</param>
 
1010
                /// <param name="isFriend">1 if friend, 0 if not.</param>
 
1011
                /// <param name="contentType">The content type of the photo, i.e. Photo, Screenshot or Other.</param>
 
1012
                /// <param name="safetyLevel">The safety level of the photo, i.e. Safe, Moderate or Restricted.</param>
 
1013
                /// <param name="hiddenFromSearch">Is the photo hidden from public searches.</param>
 
1014
                /// <returns>The id of the photograph after successful uploading.</returns>
 
1015
                public string UploadPicture(Stream stream, string title, string description, string tags, int isPublic, int isFamily, int isFriend, ContentType contentType, SafetyLevel safetyLevel, HiddenFromSearch hiddenFromSearch)
 
1016
                {
 
1017
                        /*
 
1018
                         *
 
1019
                         * Modified UploadPicture code taken from the Flickr.Net library
 
1020
                         * URL: http://workspaces.gotdotnet.com/flickrdotnet
 
1021
                         * It is used under the terms of the Common Public License 1.0
 
1022
                         * URL: http://www.opensource.org/licenses/cpl.php
 
1023
                         *
 
1024
                         * */
 
1025
 
 
1026
                        string boundary = "FLICKR_MIME_" + DateTime.Now.ToString("yyyyMMddhhmmss");
 
1027
 
 
1028
                        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(UploadUrl);
 
1029
                        req.UserAgent = "Mozilla/4.0 FlickrNet API (compatible; MSIE 6.0; Windows NT 5.1)";
 
1030
                        req.Method = "POST";
 
1031
                        if( Proxy != null ) req.Proxy = Proxy;
 
1032
                        //req.Referer = "http://www.flickr.com";
 
1033
                        req.KeepAlive = true;
 
1034
                        req.Timeout = HttpTimeout * 1000;
 
1035
                        req.ContentType = "multipart/form-data; boundary=" + boundary + "";
 
1036
                        req.Expect = "";
 
1037
 
 
1038
                        StringBuilder sb = new StringBuilder();
 
1039
 
 
1040
                        Hashtable parameters = new Hashtable();
 
1041
 
 
1042
                        if( title != null && title.Length > 0 )
 
1043
                        {
 
1044
                                parameters.Add("title", title);
 
1045
                        }
 
1046
                        if( description != null && description.Length > 0 )
 
1047
                        {
 
1048
                                parameters.Add("description", description);
 
1049
                        }
 
1050
                        if( tags != null && tags.Length > 0 )
 
1051
                        {
 
1052
                                parameters.Add("tags", tags);
 
1053
                        }
 
1054
                        if( isPublic >= 0 )
 
1055
                        {
 
1056
                                parameters.Add("is_public", isPublic.ToString());
 
1057
                        }
 
1058
                        if( isFriend >= 0 )
 
1059
                        {
 
1060
                                parameters.Add("is_friend", isFriend.ToString());
 
1061
                        }
 
1062
                        if( isFamily >= 0 )
 
1063
                        {
 
1064
                                parameters.Add("is_family", isFamily.ToString());
 
1065
                        }
 
1066
                        if( safetyLevel != SafetyLevel.None )
 
1067
                        {
 
1068
                                parameters.Add("safety_level", (int)safetyLevel);
 
1069
                        }
 
1070
                        if( contentType != ContentType.None )
 
1071
                        {
 
1072
                                parameters.Add("content_type", (int)contentType);
 
1073
                        }
 
1074
                        if( hiddenFromSearch != HiddenFromSearch.None )
 
1075
                        {
 
1076
                                parameters.Add("hidden", (int)hiddenFromSearch);
 
1077
                        }
 
1078
 
 
1079
                        parameters.Add("api_key", _apiKey);
 
1080
                        parameters.Add("auth_token", _apiToken);
 
1081
 
 
1082
                        string[] keys = new string[parameters.Keys.Count];
 
1083
                        parameters.Keys.CopyTo(keys, 0);
 
1084
                        Array.Sort(keys);
 
1085
 
 
1086
                        StringBuilder HashStringBuilder = new StringBuilder(_sharedSecret, 2 * 1024);
 
1087
 
 
1088
                        foreach(string key in keys)
 
1089
                        {
 
1090
                HashStringBuilder.Append(key);
 
1091
                HashStringBuilder.Append(parameters[key]);
 
1092
                                sb.Append("--" + boundary + "\r\n");
 
1093
                                sb.Append("Content-Disposition: form-data; name=\"" + key + "\"\r\n");
 
1094
                                sb.Append("\r\n");
 
1095
                                sb.Append(parameters[key] + "\r\n");
 
1096
                        }
 
1097
 
 
1098
                        sb.Append("--" + boundary + "\r\n");
 
1099
                        sb.Append("Content-Disposition: form-data; name=\"api_sig\"\r\n");
 
1100
                        sb.Append("\r\n");
 
1101
            sb.Append(Md5Hash(HashStringBuilder.ToString()) + "\r\n");
 
1102
 
 
1103
                        // Photo
 
1104
                        sb.Append("--" + boundary + "\r\n");
 
1105
                        sb.Append("Content-Disposition: form-data; name=\"photo\"; filename=\"image.jpeg\"\r\n");
 
1106
                        sb.Append("Content-Type: image/jpeg\r\n");
 
1107
                        sb.Append("\r\n");
 
1108
 
 
1109
                        UTF8Encoding encoding = new UTF8Encoding();
 
1110
 
 
1111
                        byte[] postContents = encoding.GetBytes(sb.ToString());
 
1112
 
 
1113
                        byte[] photoContents = new byte[stream.Length];
 
1114
                        stream.Read(photoContents, 0, photoContents.Length);
 
1115
                        stream.Close();
 
1116
 
 
1117
                        byte[] postFooter = encoding.GetBytes("\r\n--" + boundary + "--\r\n");
 
1118
 
 
1119
                        byte[] dataBuffer = new byte[postContents.Length + photoContents.Length + postFooter.Length];
 
1120
                        Buffer.BlockCopy(postContents, 0, dataBuffer, 0, postContents.Length);
 
1121
                        Buffer.BlockCopy(photoContents, 0, dataBuffer, postContents.Length, photoContents.Length);
 
1122
                        Buffer.BlockCopy(postFooter, 0, dataBuffer, postContents.Length + photoContents.Length, postFooter.Length);
 
1123
 
 
1124
                        req.ContentLength = dataBuffer.Length;
 
1125
 
 
1126
                        Stream resStream = req.GetRequestStream();
 
1127
 
 
1128
                        int j = 1;
 
1129
                        int uploadBit = Math.Max(dataBuffer.Length / 100, 50*1024);
 
1130
                        int uploadSoFar = 0;
 
1131
 
 
1132
                        for(int i = 0; i < dataBuffer.Length; i=i+uploadBit)
 
1133
                        {
 
1134
                                int toUpload = Math.Min(uploadBit, dataBuffer.Length - i);
 
1135
                                uploadSoFar += toUpload;
 
1136
 
 
1137
                                resStream.Write(dataBuffer, i, toUpload);
 
1138
 
 
1139
                                if( (OnUploadProgress != null) && ((j++) % 5 == 0 || uploadSoFar == dataBuffer.Length) )
 
1140
                                {
 
1141
                                        OnUploadProgress(this, new UploadProgressEventArgs(i+toUpload, uploadSoFar == dataBuffer.Length));
 
1142
                                }
 
1143
                        }
 
1144
                        resStream.Close();
 
1145
 
 
1146
                        HttpWebResponse res = (HttpWebResponse)req.GetResponse();
 
1147
 
 
1148
                        XmlSerializer serializer = _uploaderSerializer;
 
1149
 
 
1150
                        StreamReader sr = new StreamReader(res.GetResponseStream());
 
1151
                        string s= sr.ReadToEnd();
 
1152
                        sr.Close();
 
1153
 
 
1154
                        StringReader str = new StringReader(s);
 
1155
 
 
1156
                        FlickrNet.Uploader uploader = (FlickrNet.Uploader)serializer.Deserialize(str);
 
1157
 
 
1158
                        if( uploader.Status == ResponseStatus.OK )
 
1159
                        {
 
1160
                                return uploader.PhotoId;
 
1161
                        }
 
1162
                        else
 
1163
                        {
 
1164
                                throw new FlickrApiException(uploader.Error);
 
1165
                        }
 
1166
                }
 
1167
 
 
1168
                /// <summary>
 
1169
                /// Replace an existing photo on Flickr.
 
1170
                /// </summary>
 
1171
                /// <param name="filename">The filename of the photo to upload.</param>
 
1172
                /// <param name="photoId">The ID of the photo to replace.</param>
 
1173
                /// <returns>The id of the photograph after successful uploading.</returns>
 
1174
                public string ReplacePicture(string filename, string photoId)
 
1175
                {
 
1176
                        FileStream stream = null;
 
1177
                        try
 
1178
                        {
 
1179
                                stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
 
1180
                                return ReplacePicture(stream, photoId);
 
1181
                        }
 
1182
                        finally
 
1183
                        {
 
1184
                                if( stream != null ) stream.Close();
 
1185
                        }
 
1186
 
 
1187
                }
 
1188
 
 
1189
                /// <summary>
 
1190
                /// Replace an existing photo on Flickr.
 
1191
                /// </summary>
 
1192
                /// <param name="stream">The <see cref="Stream"/> object containing the photo to be uploaded.</param>
 
1193
                /// <param name="photoId">The ID of the photo to replace.</param>
 
1194
                /// <returns>The id of the photograph after successful uploading.</returns>
 
1195
                public string ReplacePicture(Stream stream, string photoId)
 
1196
                {
 
1197
                        string boundary = "FLICKR_MIME_" + DateTime.Now.ToString("yyyyMMddhhmmss");
 
1198
 
 
1199
                        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(ReplaceUrl);
 
1200
                        req.UserAgent = "Mozilla/4.0 FlickrNet API (compatible; MSIE 6.0; Windows NT 5.1)";
 
1201
                        req.Method = "POST";
 
1202
                        if( Proxy != null ) req.Proxy = Proxy;
 
1203
                        req.Referer = "http://www.flickr.com";
 
1204
                        req.KeepAlive = false;
 
1205
                        req.Timeout = HttpTimeout * 100;
 
1206
                        req.ContentType = "multipart/form-data; boundary=" + boundary + "";
 
1207
 
 
1208
                        StringBuilder sb = new StringBuilder();
 
1209
 
 
1210
                        Hashtable parameters = new Hashtable();
 
1211
 
 
1212
                        parameters.Add("photo_id", photoId);
 
1213
                        parameters.Add("api_key", _apiKey);
 
1214
                        parameters.Add("auth_token", _apiToken);
 
1215
 
 
1216
                        string[] keys = new string[parameters.Keys.Count];
 
1217
                        parameters.Keys.CopyTo(keys, 0);
 
1218
                        Array.Sort(keys);
 
1219
 
 
1220
                        StringBuilder HashStringBuilder = new StringBuilder(_sharedSecret, 2 * 1024);
 
1221
 
 
1222
                        foreach(string key in keys)
 
1223
                        {
 
1224
                                HashStringBuilder.Append(key);
 
1225
                                HashStringBuilder.Append(parameters[key]);
 
1226
                                sb.Append("--" + boundary + "\r\n");
 
1227
                                sb.Append("Content-Disposition: form-data; name=\"" + key + "\"\r\n");
 
1228
                                sb.Append("\r\n");
 
1229
                                sb.Append(parameters[key] + "\r\n");
 
1230
                        }
 
1231
 
 
1232
                        sb.Append("--" + boundary + "\r\n");
 
1233
                        sb.Append("Content-Disposition: form-data; name=\"api_sig\"\r\n");
 
1234
                        sb.Append("\r\n");
 
1235
                        sb.Append(Md5Hash(HashStringBuilder.ToString()) + "\r\n");
 
1236
 
 
1237
                        // Photo
 
1238
                        sb.Append("--" + boundary + "\r\n");
 
1239
                        sb.Append("Content-Disposition: form-data; name=\"photo\"; filename=\"image.jpeg\"\r\n");
 
1240
                        sb.Append("Content-Type: image/jpeg\r\n");
 
1241
                        sb.Append("\r\n");
 
1242
 
 
1243
                        UTF8Encoding encoding = new UTF8Encoding();
 
1244
 
 
1245
                        byte[] postContents = encoding.GetBytes(sb.ToString());
 
1246
 
 
1247
                        byte[] photoContents = new byte[stream.Length];
 
1248
                        stream.Read(photoContents, 0, photoContents.Length);
 
1249
                        stream.Close();
 
1250
 
 
1251
                        byte[] postFooter = encoding.GetBytes("\r\n--" + boundary + "--\r\n");
 
1252
 
 
1253
                        byte[] dataBuffer = new byte[postContents.Length + photoContents.Length + postFooter.Length];
 
1254
                        Buffer.BlockCopy(postContents, 0, dataBuffer, 0, postContents.Length);
 
1255
                        Buffer.BlockCopy(photoContents, 0, dataBuffer, postContents.Length, photoContents.Length);
 
1256
                        Buffer.BlockCopy(postFooter, 0, dataBuffer, postContents.Length + photoContents.Length, postFooter.Length);
 
1257
 
 
1258
                        req.ContentLength = dataBuffer.Length;
 
1259
 
 
1260
                        Stream resStream = req.GetRequestStream();
 
1261
 
 
1262
                        int j = 1;
 
1263
                        int uploadBit = Math.Max(dataBuffer.Length / 100, 50*1024);
 
1264
                        int uploadSoFar = 0;
 
1265
 
 
1266
                        for(int i = 0; i < dataBuffer.Length; i=i+uploadBit)
 
1267
                        {
 
1268
                                int toUpload = Math.Min(uploadBit, dataBuffer.Length - i);
 
1269
                                uploadSoFar += toUpload;
 
1270
 
 
1271
                                resStream.Write(dataBuffer, i, toUpload);
 
1272
 
 
1273
                                if( (OnUploadProgress != null) && ((j++) % 5 == 0 || uploadSoFar == dataBuffer.Length) )
 
1274
                                {
 
1275
                                        OnUploadProgress(this, new UploadProgressEventArgs(i+toUpload, uploadSoFar == dataBuffer.Length));
 
1276
                                }
 
1277
                        }
 
1278
                        resStream.Close();
 
1279
 
 
1280
                        HttpWebResponse res = (HttpWebResponse)req.GetResponse();
 
1281
 
 
1282
                        XmlSerializer serializer = _uploaderSerializer;
 
1283
 
 
1284
                        StreamReader sr = new StreamReader(res.GetResponseStream());
 
1285
                        string s= sr.ReadToEnd();
 
1286
                        sr.Close();
 
1287
 
 
1288
                        StringReader str = new StringReader(s);
 
1289
 
 
1290
                        FlickrNet.Uploader uploader = (FlickrNet.Uploader)serializer.Deserialize(str);
 
1291
 
 
1292
                        if( uploader.Status == ResponseStatus.OK )
 
1293
                        {
 
1294
                                return uploader.PhotoId;
 
1295
                        }
 
1296
                        else
 
1297
                        {
 
1298
                                throw new FlickrApiException(uploader.Error);
 
1299
                        }
 
1300
                }
 
1301
                #endregion
 
1302
 
 
1303
                #region [ Blogs ]
 
1304
                /// <summary>
 
1305
                /// Gets a list of blogs that have been set up by the user.
 
1306
                /// Requires authentication.
 
1307
                /// </summary>
 
1308
                /// <returns>A <see cref="Blogs"/> object containing the list of blogs.</returns>
 
1309
                /// <remarks></remarks>
 
1310
                public Blogs BlogGetList()
 
1311
                {
 
1312
                        Hashtable parameters = new Hashtable();
 
1313
                        parameters.Add("method", "flickr.blogs.getList");
 
1314
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1315
 
 
1316
                        if( response.Status == ResponseStatus.OK )
 
1317
                        {
 
1318
                                return response.Blogs;
 
1319
                        }
 
1320
                        else
 
1321
                        {
 
1322
                                throw new FlickrApiException(response.Error);
 
1323
                        }
 
1324
                }
 
1325
 
 
1326
                /// <summary>
 
1327
                /// Posts a photo already uploaded to a blog.
 
1328
                /// Requires authentication.
 
1329
                /// </summary>
 
1330
                /// <param name="blogId">The Id of the blog to post the photo too.</param>
 
1331
                /// <param name="photoId">The Id of the photograph to post.</param>
 
1332
                /// <param name="title">The title of the blog post.</param>
 
1333
                /// <param name="description">The body of the blog post.</param>
 
1334
                /// <returns>True if the operation is successful.</returns>
 
1335
                public bool BlogPostPhoto(string blogId, string photoId, string title, string description)
 
1336
                {
 
1337
                        return BlogPostPhoto(blogId, photoId, title, description, null);
 
1338
                }
 
1339
 
 
1340
                /// <summary>
 
1341
                /// Posts a photo already uploaded to a blog.
 
1342
                /// Requires authentication.
 
1343
                /// </summary>
 
1344
                /// <param name="blogId">The Id of the blog to post the photo too.</param>
 
1345
                /// <param name="photoId">The Id of the photograph to post.</param>
 
1346
                /// <param name="title">The title of the blog post.</param>
 
1347
                /// <param name="description">The body of the blog post.</param>
 
1348
                /// <param name="blogPassword">The password of the blog if it is not already stored in flickr.</param>
 
1349
                /// <returns>True if the operation is successful.</returns>
 
1350
                public bool BlogPostPhoto(string blogId, string photoId, string title, string description, string blogPassword)
 
1351
                {
 
1352
                        Hashtable parameters = new Hashtable();
 
1353
                        parameters.Add("method", "flickr.blogs.postPhoto");
 
1354
                        parameters.Add("blog_id", blogId);
 
1355
                        parameters.Add("photo_id", photoId);
 
1356
                        parameters.Add("title", title);
 
1357
                        parameters.Add("description", description);
 
1358
                        if( blogPassword != null ) parameters.Add("blog_password", blogPassword);
 
1359
 
 
1360
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1361
 
 
1362
                        if( response.Status == ResponseStatus.OK )
 
1363
                        {
 
1364
                                return true;
 
1365
                        }
 
1366
                        else
 
1367
                        {
 
1368
                                throw new FlickrApiException(response.Error);
 
1369
                        }
 
1370
                }
 
1371
                #endregion
 
1372
 
 
1373
                #region [ Contacts ]
 
1374
                /// <summary>
 
1375
                /// Gets a list of contacts for the logged in user.
 
1376
                /// Requires authentication.
 
1377
                /// </summary>
 
1378
                /// <returns>An instance of the <see cref="Contacts"/> class containing the list of contacts.</returns>
 
1379
                public Contacts ContactsGetList()
 
1380
                {
 
1381
                        Hashtable parameters = new Hashtable();
 
1382
                        parameters.Add("method", "flickr.contacts.getList");
 
1383
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1384
 
 
1385
                        if( response.Status == ResponseStatus.OK )
 
1386
                        {
 
1387
                                return response.Contacts;
 
1388
                        }
 
1389
                        else
 
1390
                        {
 
1391
                                throw new FlickrApiException(response.Error);
 
1392
                        }
 
1393
                }
 
1394
 
 
1395
                /// <summary>
 
1396
                /// Gets a list of the given users contact, or those that are publically avaiable.
 
1397
                /// </summary>
 
1398
                /// <param name="userId">The Id of the user who's contacts you want to return.</param>
 
1399
                /// <returns>An instance of the <see cref="Contacts"/> class containing the list of contacts.</returns>
 
1400
                public Contacts ContactsGetPublicList(string userId)
 
1401
                {
 
1402
                        Hashtable parameters = new Hashtable();
 
1403
                        parameters.Add("method", "flickr.contacts.getPublicList");
 
1404
                        parameters.Add("user_id", userId);
 
1405
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1406
 
 
1407
                        if( response.Status == ResponseStatus.OK )
 
1408
                        {
 
1409
                                return response.Contacts;
 
1410
                        }
 
1411
                        else
 
1412
                        {
 
1413
                                throw new FlickrApiException(response.Error);
 
1414
                        }
 
1415
                }
 
1416
                #endregion
 
1417
 
 
1418
                #region [ Favorites ]
 
1419
                /// <summary>
 
1420
                /// Adds a photo to the logged in favourites.
 
1421
                /// Requires authentication.
 
1422
                /// </summary>
 
1423
                /// <param name="photoId">The id of the photograph to add.</param>
 
1424
                /// <returns>True if the operation is successful.</returns>
 
1425
                public bool FavoritesAdd(string photoId)
 
1426
                {
 
1427
                        Hashtable parameters = new Hashtable();
 
1428
                        parameters.Add("method", "flickr.favorites.add");
 
1429
                        parameters.Add("photo_id", photoId);
 
1430
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1431
 
 
1432
                        if( response.Status == ResponseStatus.OK )
 
1433
                        {
 
1434
                                return true;
 
1435
                        }
 
1436
                        else
 
1437
                        {
 
1438
                                throw new FlickrApiException(response.Error);
 
1439
                        }
 
1440
                }
 
1441
 
 
1442
                /// <summary>
 
1443
                /// Removes a photograph from the logged in users favourites.
 
1444
                /// Requires authentication.
 
1445
                /// </summary>
 
1446
                /// <param name="photoId">The id of the photograph to remove.</param>
 
1447
                /// <returns>True if the operation is successful.</returns>
 
1448
                public bool FavoritesRemove(string photoId)
 
1449
                {
 
1450
                        Hashtable parameters = new Hashtable();
 
1451
                        parameters.Add("method", "flickr.favorites.remove");
 
1452
                        parameters.Add("photo_id", photoId);
 
1453
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1454
 
 
1455
                        if( response.Status == ResponseStatus.OK )
 
1456
                        {
 
1457
                                return true;
 
1458
                        }
 
1459
                        else
 
1460
                        {
 
1461
                                throw new FlickrApiException(response.Error);
 
1462
                        }
 
1463
                }
 
1464
 
 
1465
                /// <summary>
 
1466
                /// Get a list of the currently logger in users favourites.
 
1467
                /// Requires authentication.
 
1468
                /// </summary>
 
1469
                /// <returns><see cref="Photos"/> instance containing a collection of <see cref="Photo"/> objects.</returns>
 
1470
                public Photos FavoritesGetList()
 
1471
                {
 
1472
                        return FavoritesGetList(null, 0, 0);
 
1473
                }
 
1474
 
 
1475
                /// <summary>
 
1476
                /// Get a list of the currently logger in users favourites.
 
1477
                /// Requires authentication.
 
1478
                /// </summary>
 
1479
                /// <param name="perPage">Number of photos to include per page.</param>
 
1480
                /// <param name="page">The page to download this time.</param>
 
1481
                /// <returns><see cref="Photos"/> instance containing a collection of <see cref="Photo"/> objects.</returns>
 
1482
                public Photos FavoritesGetList(int perPage, int page)
 
1483
                {
 
1484
                        return FavoritesGetList(null, perPage, page);
 
1485
                }
 
1486
 
 
1487
                /// <summary>
 
1488
                /// Get a list of favourites for the specified user.
 
1489
                /// </summary>
 
1490
                /// <param name="userId">The user id of the user whose favourites you wish to retrieve.</param>
 
1491
                /// <returns><see cref="Photos"/> instance containing a collection of <see cref="Photo"/> objects.</returns>
 
1492
                public Photos FavoritesGetList(string userId)
 
1493
                {
 
1494
                        return FavoritesGetList(userId, 0, 0);
 
1495
                }
 
1496
 
 
1497
                /// <summary>
 
1498
                /// Get a list of favourites for the specified user.
 
1499
                /// </summary>
 
1500
                /// <param name="userId">The user id of the user whose favourites you wish to retrieve.</param>
 
1501
                /// <param name="perPage">Number of photos to include per page.</param>
 
1502
                /// <param name="page">The page to download this time.</param>
 
1503
                /// <returns><see cref="Photos"/> instance containing a collection of <see cref="Photo"/> objects.</returns>
 
1504
                public Photos FavoritesGetList(string userId, int perPage, int page)
 
1505
                {
 
1506
                        Hashtable parameters = new Hashtable();
 
1507
                        parameters.Add("method", "flickr.favorites.getList");
 
1508
                        if( userId != null ) parameters.Add("user_id", userId);
 
1509
                        if( perPage > 0 ) parameters.Add("per_page", perPage.ToString());
 
1510
                        if( page > 0 ) parameters.Add("page", page.ToString());
 
1511
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1512
 
 
1513
                        if( response.Status == ResponseStatus.OK )
 
1514
                        {
 
1515
                                return response.Photos;
 
1516
                        }
 
1517
                        else
 
1518
                        {
 
1519
                                throw new FlickrApiException(response.Error);
 
1520
                        }
 
1521
                }
 
1522
 
 
1523
                /// <summary>
 
1524
                /// Gets the public favourites for a specified user.
 
1525
                /// </summary>
 
1526
                /// <remarks>This function difers from <see cref="Flickr.FavoritesGetList(string)"/> in that the user id
 
1527
                /// is not optional.</remarks>
 
1528
                /// <param name="userId">The is of the user whose favourites you wish to return.</param>
 
1529
                /// <returns>A <see cref="Photos"/> object containing a collection of <see cref="Photo"/> objects.</returns>
 
1530
                public Photos FavoritesGetPublicList(string userId)
 
1531
                {
 
1532
                        return FavoritesGetPublicList(userId, 0, 0);
 
1533
                }
 
1534
 
 
1535
                /// <summary>
 
1536
                /// Gets the public favourites for a specified user.
 
1537
                /// </summary>
 
1538
                /// <remarks>This function difers from <see cref="Flickr.FavoritesGetList(string)"/> in that the user id
 
1539
                /// is not optional.</remarks>
 
1540
                /// <param name="userId">The is of the user whose favourites you wish to return.</param>
 
1541
                /// <param name="perPage">The number of photos to return per page.</param>
 
1542
                /// <param name="page">The specific page to return.</param>
 
1543
                /// <returns>A <see cref="Photos"/> object containing a collection of <see cref="Photo"/> objects.</returns>
 
1544
                public Photos FavoritesGetPublicList(string userId, int perPage, int page)
 
1545
                {
 
1546
                        Hashtable parameters = new Hashtable();
 
1547
                        parameters.Add("method", "flickr.favorites.getPublicList");
 
1548
                        parameters.Add("user_id", userId);
 
1549
                        if( perPage > 0 ) parameters.Add("per_page", perPage.ToString());
 
1550
                        if( page > 0 ) parameters.Add("page", page.ToString());
 
1551
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1552
 
 
1553
                        if( response.Status == ResponseStatus.OK )
 
1554
                        {
 
1555
                                return response.Photos;
 
1556
                        }
 
1557
                        else
 
1558
                        {
 
1559
                                throw new FlickrApiException(response.Error);
 
1560
                        }
 
1561
                }
 
1562
                #endregion
 
1563
 
 
1564
                #region [ Groups ]
 
1565
                /// <summary>
 
1566
                /// Returns the top <see cref="Category"/> with a list of sub-categories and groups.
 
1567
                /// (The top category does not have any groups in it but others may).
 
1568
                /// </summary>
 
1569
                /// <returns>A <see cref="Category"/> instance.</returns>
 
1570
                public Category GroupsBrowse()
 
1571
                {
 
1572
                        return GroupsBrowse("0");
 
1573
                }
 
1574
 
 
1575
                /// <summary>
 
1576
                /// Returns the <see cref="Category"/> specified by the category id with a list of sub-categories and groups.
 
1577
                /// </summary>
 
1578
                /// <param name="catId"></param>
 
1579
                /// <returns>A <see cref="Category"/> instance.</returns>
 
1580
                public Category GroupsBrowse(string catId)
 
1581
                {
 
1582
                        Hashtable parameters = new Hashtable();
 
1583
                        parameters.Add("method", "flickr.groups.browse");
 
1584
                        parameters.Add("cat_id", catId);
 
1585
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1586
 
 
1587
                        if( response.Status == ResponseStatus.OK )
 
1588
                        {
 
1589
                                return response.Category;
 
1590
                        }
 
1591
                        else
 
1592
                        {
 
1593
                                throw new FlickrApiException(response.Error);
 
1594
                        }
 
1595
                }
 
1596
 
 
1597
                /// <summary>
 
1598
                /// Search the list of groups on Flickr for the text.
 
1599
                /// </summary>
 
1600
                /// <param name="text">The text to search for.</param>
 
1601
                /// <returns>A list of groups matching the search criteria.</returns>
 
1602
                public GroupSearchResults GroupsSearch(string text)
 
1603
                {
 
1604
                        return GroupsSearch(text, 0, 0);
 
1605
                }
 
1606
 
 
1607
                /// <summary>
 
1608
                /// Search the list of groups on Flickr for the text.
 
1609
                /// </summary>
 
1610
                /// <param name="text">The text to search for.</param>
 
1611
                /// <param name="page">The page of the results to return.</param>
 
1612
                /// <returns>A list of groups matching the search criteria.</returns>
 
1613
                public GroupSearchResults GroupsSearch(string text, int page)
 
1614
                {
 
1615
                        return GroupsSearch(text, page, 0);
 
1616
                }
 
1617
 
 
1618
                /// <summary>
 
1619
                /// Search the list of groups on Flickr for the text.
 
1620
                /// </summary>
 
1621
                /// <param name="text">The text to search for.</param>
 
1622
                /// <param name="page">The page of the results to return.</param>
 
1623
                /// <param name="perPage">The number of groups to list per page.</param>
 
1624
                /// <returns>A list of groups matching the search criteria.</returns>
 
1625
                public GroupSearchResults GroupsSearch(string text, int page, int perPage)
 
1626
                {
 
1627
                        Hashtable parameters = new Hashtable();
 
1628
                        parameters.Add("method", "flickr.groups.search");
 
1629
                        parameters.Add("api_key", _apiKey);
 
1630
                        parameters.Add("text", text);
 
1631
                        if( page > 0 ) parameters.Add("page", page.ToString());
 
1632
                        if( perPage > 0 ) parameters.Add("per_page", perPage.ToString());
 
1633
 
 
1634
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1635
 
 
1636
                        if( response.Status == ResponseStatus.OK )
 
1637
                        {
 
1638
                                return new GroupSearchResults(response.AllElements[0]);
 
1639
                        }
 
1640
                        else
 
1641
                        {
 
1642
                                throw new FlickrApiException(response.Error);
 
1643
                        }
 
1644
                }
 
1645
 
 
1646
                /// <summary>
 
1647
                /// Returns a <see cref="GroupFullInfo"/> object containing details about a group.
 
1648
                /// </summary>
 
1649
                /// <param name="groupId">The id of the group to return.</param>
 
1650
                /// <returns>The <see cref="GroupFullInfo"/> specified by the group id.</returns>
 
1651
                public GroupFullInfo GroupsGetInfo(string groupId)
 
1652
                {
 
1653
                        Hashtable parameters = new Hashtable();
 
1654
                        parameters.Add("method", "flickr.groups.getInfo");
 
1655
                        parameters.Add("api_key", _apiKey);
 
1656
                        parameters.Add("group_id", groupId);
 
1657
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1658
 
 
1659
                        if( response.Status == ResponseStatus.OK )
 
1660
                        {
 
1661
                                return new GroupFullInfo(response.AllElements[0]);
 
1662
                        }
 
1663
                        else
 
1664
                        {
 
1665
                                throw new FlickrApiException(response.Error);
 
1666
                        }
 
1667
                }
 
1668
                #endregion
 
1669
 
 
1670
                #region [ Group Pool ]
 
1671
                /// <summary>
 
1672
                /// Adds a photo to a pool you have permission to add photos to.
 
1673
                /// </summary>
 
1674
                /// <param name="photoId">The id of one of your photos to be added.</param>
 
1675
                /// <param name="groupId">The id of a group you are a member of.</param>
 
1676
                /// <returns>True on a successful addition.</returns>
 
1677
                public bool GroupPoolAdd(string photoId, string groupId)
 
1678
                {
 
1679
                        Hashtable parameters = new Hashtable();
 
1680
                        parameters.Add("method", "flickr.groups.pools.add");
 
1681
                        parameters.Add("photo_id", photoId);
 
1682
                        parameters.Add("group_id", groupId);
 
1683
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1684
 
 
1685
                        if( response.Status == ResponseStatus.OK )
 
1686
                        {
 
1687
                                return true;
 
1688
                        }
 
1689
                        else
 
1690
                        {
 
1691
                                throw new FlickrApiException(response.Error);
 
1692
                        }
 
1693
                }
 
1694
 
 
1695
                /// <summary>
 
1696
                /// Gets the context for a photo from within a group. This provides the
 
1697
                /// id and thumbnail url for the next and previous photos in the group.
 
1698
                /// </summary>
 
1699
                /// <param name="photoId">The Photo ID for the photo you want the context for.</param>
 
1700
                /// <param name="groupId">The group ID for the group you want the context to be relevant to.</param>
 
1701
                /// <returns>The <see cref="Context"/> of the photo in the group.</returns>
 
1702
                public Context GroupPoolGetContext(string photoId, string groupId)
 
1703
                {
 
1704
                        Hashtable parameters = new Hashtable();
 
1705
                        parameters.Add("method", "flickr.groups.pools.getContext");
 
1706
                        parameters.Add("photo_id", photoId);
 
1707
                        parameters.Add("group_id", groupId);
 
1708
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1709
 
 
1710
                        if( response.Status == ResponseStatus.OK )
 
1711
                        {
 
1712
                                Context context = new Context();
 
1713
                                context.Count = response.ContextCount.Count;
 
1714
                                context.NextPhoto = response.ContextNextPhoto;
 
1715
                                context.PreviousPhoto = response.ContextPrevPhoto;
 
1716
                                return context;
 
1717
                        }
 
1718
                        else
 
1719
                        {
 
1720
                                throw new FlickrApiException(response.Error);
 
1721
                        }
 
1722
                }
 
1723
 
 
1724
                /// <summary>
 
1725
                /// Remove a picture from a group.
 
1726
                /// </summary>
 
1727
                /// <param name="photoId">The id of one of your pictures you wish to remove.</param>
 
1728
                /// <param name="groupId">The id of the group to remove the picture from.</param>
 
1729
                /// <returns>True if the photo is successfully removed.</returns>
 
1730
                public bool GroupPoolRemove(string photoId, string groupId)
 
1731
                {
 
1732
                        Hashtable parameters = new Hashtable();
 
1733
                        parameters.Add("method", "flickr.groups.pools.remove");
 
1734
                        parameters.Add("photo_id", photoId);
 
1735
                        parameters.Add("group_id", groupId);
 
1736
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1737
 
 
1738
                        if( response.Status == ResponseStatus.OK )
 
1739
                        {
 
1740
                                return true;
 
1741
                        }
 
1742
                        else
 
1743
                        {
 
1744
                                throw new FlickrApiException(response.Error);
 
1745
                        }
 
1746
                }
 
1747
 
 
1748
                /// <summary>
 
1749
                /// Gets a list of
 
1750
                /// </summary>
 
1751
                /// <returns></returns>
 
1752
                public MemberGroupInfo[] GroupPoolGetGroups()
 
1753
                {
 
1754
                        Hashtable parameters = new Hashtable();
 
1755
                        parameters.Add("method", "flickr.groups.pools.getGroups");
 
1756
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1757
 
 
1758
                        if( response.Status == ResponseStatus.OK )
 
1759
                        {
 
1760
                                return MemberGroupInfo.GetMemberGroupInfo(response.AllElements[0]);
 
1761
                        }
 
1762
                        else
 
1763
                        {
 
1764
                                throw new FlickrApiException(response.Error);
 
1765
                        }
 
1766
                }
 
1767
 
 
1768
                /// <summary>
 
1769
                /// Gets a list of photos for a given group.
 
1770
                /// </summary>
 
1771
                /// <param name="groupId">The group ID for the group.</param>
 
1772
                /// <returns>A <see cref="Photos"/> object containing the list of photos.</returns>
 
1773
                public Photos GroupPoolGetPhotos(string groupId)
 
1774
                {
 
1775
                        return GroupPoolGetPhotos(groupId, null, null, PhotoSearchExtras.All, 0, 0);
 
1776
                }
 
1777
 
 
1778
                /// <summary>
 
1779
                /// Gets a list of photos for a given group.
 
1780
                /// </summary>
 
1781
                /// <param name="groupId">The group ID for the group.</param>
 
1782
                /// <param name="tags">Space seperated list of tags that photos returned must have.</param>
 
1783
                /// <returns>A <see cref="Photos"/> object containing the list of photos.</returns>
 
1784
                public Photos GroupPoolGetPhotos(string groupId, string tags)
 
1785
                {
 
1786
                        return GroupPoolGetPhotos(groupId, tags, null, PhotoSearchExtras.All, 0, 0);
 
1787
                }
 
1788
 
 
1789
                /// <summary>
 
1790
                /// Gets a list of photos for a given group.
 
1791
                /// </summary>
 
1792
                /// <param name="groupId">The group ID for the group.</param>
 
1793
                /// <param name="perPage">The number of photos per page.</param>
 
1794
                /// <param name="page">The page to return.</param>
 
1795
                /// <returns>A <see cref="Photos"/> object containing the list of photos.</returns>
 
1796
                public Photos GroupPoolGetPhotos(string groupId, int perPage, int page)
 
1797
                {
 
1798
                        return GroupPoolGetPhotos(groupId, null, null, PhotoSearchExtras.All, perPage, page);
 
1799
                }
 
1800
 
 
1801
                /// <summary>
 
1802
                /// Gets a list of photos for a given group.
 
1803
                /// </summary>
 
1804
                /// <param name="groupId">The group ID for the group.</param>
 
1805
                /// <param name="tags">Space seperated list of tags that photos returned must have.</param>
 
1806
                /// <param name="perPage">The number of photos per page.</param>
 
1807
                /// <param name="page">The page to return.</param>
 
1808
                /// <returns>A <see cref="Photos"/> object containing the list of photos.</returns>
 
1809
                public Photos GroupPoolGetPhotos(string groupId, string tags, int perPage, int page)
 
1810
                {
 
1811
                        return GroupPoolGetPhotos(groupId, tags, null, PhotoSearchExtras.All, perPage, page);
 
1812
                }
 
1813
 
 
1814
                /// <summary>
 
1815
                /// Gets a list of photos for a given group.
 
1816
                /// </summary>
 
1817
                /// <param name="groupId">The group ID for the group.</param>
 
1818
                /// <param name="tags">Space seperated list of tags that photos returned must have.
 
1819
                /// Currently only supports 1 tag at a time.</param>
 
1820
                /// <param name="userId">The group member to return photos for.</param>
 
1821
                /// <param name="extras">The <see cref="PhotoSearchExtras"/> specifying which extras to return. All other overloads default to returning all extras.</param>
 
1822
                /// <param name="perPage">The number of photos per page.</param>
 
1823
                /// <param name="page">The page to return.</param>
 
1824
                /// <returns>A <see cref="Photos"/> object containing the list of photos.</returns>
 
1825
                public Photos GroupPoolGetPhotos(string groupId, string tags, string userId, PhotoSearchExtras extras, int perPage, int page)
 
1826
                {
 
1827
                        Hashtable parameters = new Hashtable();
 
1828
                        parameters.Add("method", "flickr.groups.pools.getPhotos");
 
1829
                        parameters.Add("group_id", groupId);
 
1830
                        if( tags != null && tags.Length > 0 )parameters.Add("tags", tags);
 
1831
                        if( perPage > 0 ) parameters.Add("per_page", perPage.ToString());
 
1832
                        if( page > 0 ) parameters.Add("page", page.ToString());
 
1833
                        if( userId != null && userId.Length > 0 ) parameters.Add("user_id", userId);
 
1834
                        if( extras != PhotoSearchExtras.None ) parameters.Add("extras", Utils.ExtrasToString(extras));
 
1835
 
 
1836
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1837
 
 
1838
                        if( response.Status == ResponseStatus.OK )
 
1839
                        {
 
1840
                                return response.Photos;
 
1841
                        }
 
1842
                        else
 
1843
                        {
 
1844
                                throw new FlickrApiException(response.Error);
 
1845
                        }
 
1846
                }
 
1847
                #endregion
 
1848
 
 
1849
                #region [ Interestingness ]
 
1850
                /// <summary>
 
1851
                /// Gets a list of photos from the most recent interstingness list.
 
1852
                /// </summary>
 
1853
                /// <param name="perPage">Number of photos per page.</param>
 
1854
                /// <param name="page">The page number to return.</param>
 
1855
                /// <param name="extras"><see cref="PhotoSearchExtras"/> enumeration.</param>
 
1856
                /// <returns><see cref="Photos"/> instance containing list of photos.</returns>
 
1857
                public Photos InterestingnessGetList(PhotoSearchExtras extras, int perPage, int page)
 
1858
                {
 
1859
                        return InterestingnessGetList(DateTime.MinValue, extras, perPage, page);
 
1860
                }
 
1861
 
 
1862
                /// <summary>
 
1863
                /// Gets a list of photos from the interstingness list for the specified date.
 
1864
                /// </summary>
 
1865
                /// <param name="date">The date to return the interestingness list for.</param>
 
1866
                /// <returns><see cref="Photos"/> instance containing list of photos.</returns>
 
1867
                public Photos InterestingnessGetList(DateTime date)
 
1868
                {
 
1869
                        return InterestingnessGetList(date, PhotoSearchExtras.All, 0, 0);
 
1870
                }
 
1871
 
 
1872
                /// <summary>
 
1873
                /// Gets a list of photos from the most recent interstingness list.
 
1874
                /// </summary>
 
1875
                /// <returns><see cref="Photos"/> instance containing list of photos.</returns>
 
1876
                public Photos InterestingnessGetList()
 
1877
                {
 
1878
                        return InterestingnessGetList(DateTime.MinValue, PhotoSearchExtras.All, 0, 0);
 
1879
                }
 
1880
 
 
1881
                /// <summary>
 
1882
                /// Gets a list of photos from the most recent interstingness list.
 
1883
                /// </summary>
 
1884
                /// <param name="date">The date to return the interestingness photos for.</param>
 
1885
                /// <param name="extras">The extra parameters to return along with the search results.
 
1886
                /// See <see cref="PhotoSearchOptions"/> for more details.</param>
 
1887
                /// <param name="perPage">The number of results to return per page.</param>
 
1888
                /// <param name="page">The page of the results to return.</param>
 
1889
                /// <returns></returns>
 
1890
                public Photos InterestingnessGetList(DateTime date, PhotoSearchExtras extras, int perPage, int page)
 
1891
                {
 
1892
                        Hashtable parameters = new Hashtable();
 
1893
                        parameters.Add("method", "flickr.interestingness.getList");
 
1894
 
 
1895
                        if( date > DateTime.MinValue ) parameters.Add("date", date.ToString("yyyy-MM-dd"));
 
1896
                        if( perPage > 0 ) parameters.Add("per_page", perPage.ToString());
 
1897
                        if( page > 0 ) parameters.Add("page", page.ToString());
 
1898
                        if( extras != PhotoSearchExtras.None )
 
1899
                                parameters.Add("extras", Utils.ExtrasToString(extras));
 
1900
 
 
1901
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1902
 
 
1903
                        if( response.Status == ResponseStatus.OK )
 
1904
                        {
 
1905
                                return response.Photos;
 
1906
                        }
 
1907
                        else
 
1908
                        {
 
1909
                                throw new FlickrApiException(response.Error);
 
1910
                        }
 
1911
                }
 
1912
 
 
1913
 
 
1914
                #endregion
 
1915
 
 
1916
                #region [ Notes ]
 
1917
                /// <summary>
 
1918
                /// Add a note to a picture.
 
1919
                /// </summary>
 
1920
                /// <param name="photoId">The photo id to add the note to.</param>
 
1921
                /// <param name="noteX">The X co-ordinate of the upper left corner of the note.</param>
 
1922
                /// <param name="noteY">The Y co-ordinate of the upper left corner of the note.</param>
 
1923
                /// <param name="noteWidth">The width of the note.</param>
 
1924
                /// <param name="noteHeight">The height of the note.</param>
 
1925
                /// <param name="noteText">The text in the note.</param>
 
1926
                /// <returns></returns>
 
1927
                public string NotesAdd(string photoId, int noteX, int noteY, int noteWidth, int noteHeight, string noteText)
 
1928
                {
 
1929
                        Hashtable parameters = new Hashtable();
 
1930
                        parameters.Add("method", "flickr.photos.notes.add");
 
1931
                        parameters.Add("photo_id", photoId);
 
1932
                        parameters.Add("note_x", noteX.ToString());
 
1933
                        parameters.Add("note_y", noteY.ToString());
 
1934
                        parameters.Add("note_w", noteWidth.ToString());
 
1935
                        parameters.Add("note_h", noteHeight.ToString());
 
1936
                        parameters.Add("note_text", noteText);
 
1937
 
 
1938
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1939
 
 
1940
                        if( response.Status == ResponseStatus.OK )
 
1941
                        {
 
1942
                                foreach(XmlElement element in response.AllElements)
 
1943
                                {
 
1944
                                        return element.Attributes["id", ""].Value;
 
1945
                                }
 
1946
                                return string.Empty;
 
1947
                        }
 
1948
                        else
 
1949
                        {
 
1950
                                throw new FlickrApiException(response.Error);
 
1951
                        }
 
1952
                }
 
1953
 
 
1954
                /// <summary>
 
1955
                /// Edit and update a note.
 
1956
                /// </summary>
 
1957
                /// <param name="noteId">The ID of the note to update.</param>
 
1958
                /// <param name="noteX">The X co-ordinate of the upper left corner of the note.</param>
 
1959
                /// <param name="noteY">The Y co-ordinate of the upper left corner of the note.</param>
 
1960
                /// <param name="noteWidth">The width of the note.</param>
 
1961
                /// <param name="noteHeight">The height of the note.</param>
 
1962
                /// <param name="noteText">The new text in the note.</param>
 
1963
                public void NotesEdit(string noteId, int noteX, int noteY, int noteWidth, int noteHeight, string noteText)
 
1964
                {
 
1965
                        Hashtable parameters = new Hashtable();
 
1966
                        parameters.Add("method", "flickr.photos.notes.edit");
 
1967
                        parameters.Add("note_id", noteId);
 
1968
                        parameters.Add("note_x", noteX.ToString());
 
1969
                        parameters.Add("note_y", noteY.ToString());
 
1970
                        parameters.Add("note_w", noteWidth.ToString());
 
1971
                        parameters.Add("note_h", noteHeight.ToString());
 
1972
                        parameters.Add("note_text", noteText);
 
1973
 
 
1974
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1975
 
 
1976
                        if( response.Status == ResponseStatus.OK )
 
1977
                        {
 
1978
                                return;
 
1979
                        }
 
1980
                        else
 
1981
                        {
 
1982
                                throw new FlickrApiException(response.Error);
 
1983
                        }
 
1984
                }
 
1985
 
 
1986
                /// <summary>
 
1987
                /// Delete an existing note.
 
1988
                /// </summary>
 
1989
                /// <param name="noteId">The ID of the note.</param>
 
1990
                public void NotesDelete(string noteId)
 
1991
                {
 
1992
                        Hashtable parameters = new Hashtable();
 
1993
                        parameters.Add("method", "flickr.photos.notes.delete");
 
1994
                        parameters.Add("note_id", noteId);
 
1995
 
 
1996
                        FlickrNet.Response response = GetResponseCache(parameters);
 
1997
 
 
1998
                        if( response.Status == ResponseStatus.OK )
 
1999
                        {
 
2000
                                return;
 
2001
                        }
 
2002
                        else
 
2003
                        {
 
2004
                                throw new FlickrApiException(response.Error);
 
2005
                        }
 
2006
                }
 
2007
                #endregion
 
2008
 
 
2009
                #region [ People ]
 
2010
                /// <summary>
 
2011
                /// Used to fid a flickr users details by specifying their email address.
 
2012
                /// </summary>
 
2013
                /// <param name="emailAddress">The email address to search on.</param>
 
2014
                /// <returns>The <see cref="FoundUser"/> object containing the matching details.</returns>
 
2015
                /// <exception cref="FlickrException">A FlickrException is raised if the email address is not found.</exception>
 
2016
                public FoundUser PeopleFindByEmail(string emailAddress)
 
2017
                {
 
2018
                        Hashtable parameters = new Hashtable();
 
2019
                        parameters.Add("method", "flickr.people.findByEmail");
 
2020
                        parameters.Add("api_key", _apiKey);
 
2021
                        parameters.Add("find_email", emailAddress);
 
2022
 
 
2023
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2024
 
 
2025
                        if( response.Status == ResponseStatus.OK )
 
2026
                        {
 
2027
                                return new FoundUser(response.AllElements[0]);
 
2028
                        }
 
2029
                        else
 
2030
                        {
 
2031
                                throw new FlickrApiException(response.Error);
 
2032
                        }
 
2033
                }
 
2034
 
 
2035
                /// <summary>
 
2036
                /// Returns a <see cref="FoundUser"/> object matching the screen name.
 
2037
                /// </summary>
 
2038
                /// <param name="username">The screen name or username of the user.</param>
 
2039
                /// <returns>A <see cref="FoundUser"/> class containing the userId and username of the user.</returns>
 
2040
                /// <exception cref="FlickrException">A FlickrException is raised if the email address is not found.</exception>
 
2041
                public FoundUser PeopleFindByUsername(string username)
 
2042
                {
 
2043
                        Hashtable parameters = new Hashtable();
 
2044
                        parameters.Add("method", "flickr.people.findByUsername");
 
2045
                        parameters.Add("api_key", _apiKey);
 
2046
                        parameters.Add("username", username);
 
2047
 
 
2048
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2049
 
 
2050
                        if( response.Status == ResponseStatus.OK )
 
2051
                        {
 
2052
                                return new FoundUser(response.AllElements[0]);
 
2053
                        }
 
2054
                        else
 
2055
                        {
 
2056
                                throw new FlickrApiException(response.Error);
 
2057
                        }
 
2058
                }
 
2059
 
 
2060
                /// <summary>
 
2061
                /// Gets the <see cref="Person"/> object for the given user id.
 
2062
                /// </summary>
 
2063
                /// <param name="userId">The user id to find.</param>
 
2064
                /// <returns>The <see cref="Person"/> object containing the users details.</returns>
 
2065
                public Person PeopleGetInfo(string userId)
 
2066
                {
 
2067
                        Hashtable parameters = new Hashtable();
 
2068
                        parameters.Add("method", "flickr.people.getInfo");
 
2069
                        parameters.Add("api_key", _apiKey);
 
2070
                        parameters.Add("user_id", userId);
 
2071
 
 
2072
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2073
 
 
2074
                        if( response.Status == ResponseStatus.OK )
 
2075
                        {
 
2076
                                return Person.SerializePerson(response.AllElements[0]);
 
2077
                        }
 
2078
                        else
 
2079
                        {
 
2080
                                throw new FlickrApiException(response.Error);
 
2081
                        }
 
2082
                }
 
2083
 
 
2084
                /// <summary>
 
2085
                /// Gets the upload status of the authenticated user.
 
2086
                /// </summary>
 
2087
                /// <returns>The <see cref="UserStatus"/> object containing the users details.</returns>
 
2088
                public UserStatus PeopleGetUploadStatus()
 
2089
                {
 
2090
                        Hashtable parameters = new Hashtable();
 
2091
                        parameters.Add("method", "flickr.people.getUploadStatus");
 
2092
 
 
2093
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2094
 
 
2095
                        if( response.Status == ResponseStatus.OK )
 
2096
                        {
 
2097
                                return new UserStatus(response.AllElements[0]);
 
2098
                        }
 
2099
                        else
 
2100
                        {
 
2101
                                throw new FlickrApiException(response.Error);
 
2102
                        }
 
2103
                }
 
2104
 
 
2105
                /// <summary>
 
2106
                /// Get a list of public groups for a user.
 
2107
                /// </summary>
 
2108
                /// <param name="userId">The user id to get groups for.</param>
 
2109
                /// <returns>An array of <see cref="PublicGroupInfo"/> instances.</returns>
 
2110
                public PublicGroupInfo[] PeopleGetPublicGroups(string userId)
 
2111
                {
 
2112
                        Hashtable parameters = new Hashtable();
 
2113
                        parameters.Add("method", "flickr.people.getPublicGroups");
 
2114
                        parameters.Add("api_key", _apiKey);
 
2115
                        parameters.Add("user_id", userId);
 
2116
 
 
2117
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2118
 
 
2119
                        if( response.Status == ResponseStatus.OK )
 
2120
                        {
 
2121
                                return PublicGroupInfo.GetPublicGroupInfo(response.AllElements[0]);
 
2122
                        }
 
2123
                        else
 
2124
                        {
 
2125
                                throw new FlickrApiException(response.Error);
 
2126
                        }
 
2127
                }
 
2128
 
 
2129
                /// <summary>
 
2130
                /// Gets a users public photos. Excludes private photos.
 
2131
                /// </summary>
 
2132
                /// <param name="userId">The user id of the user.</param>
 
2133
                /// <returns>The collection of photos contained within a <see cref="Photo"/> object.</returns>
 
2134
                public Photos PeopleGetPublicPhotos(string userId)
 
2135
                {
 
2136
                        Hashtable parameters = new Hashtable();
 
2137
                        parameters.Add("method", "flickr.people.getPublicPhotos");
 
2138
                        parameters.Add("api_key", _apiKey);
 
2139
                        parameters.Add("user_id", userId);
 
2140
 
 
2141
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2142
 
 
2143
                        if( response.Status == ResponseStatus.OK )
 
2144
                        {
 
2145
                                return response.Photos;
 
2146
                        }
 
2147
                        else
 
2148
                        {
 
2149
                                throw new FlickrApiException(response.Error);
 
2150
                        }
 
2151
                }
 
2152
                #endregion
 
2153
 
 
2154
                #region [ Photos ]
 
2155
                /// <summary>
 
2156
                /// Add a selection of tags to a photo.
 
2157
                /// </summary>
 
2158
                /// <param name="photoId">The photo id of the photo.</param>
 
2159
                /// <param name="tags">An array of strings containing the tags.</param>
 
2160
                /// <returns>True if the tags are added successfully.</returns>
 
2161
                public void PhotosAddTags(string photoId, string[] tags)
 
2162
                {
 
2163
                        string s = string.Join(",", tags);
 
2164
                        PhotosAddTags(photoId, s);
 
2165
                }
 
2166
 
 
2167
                /// <summary>
 
2168
                /// Add a selection of tags to a photo.
 
2169
                /// </summary>
 
2170
                /// <param name="photoId">The photo id of the photo.</param>
 
2171
                /// <param name="tags">An string of comma delimited tags.</param>
 
2172
                /// <returns>True if the tags are added successfully.</returns>
 
2173
                public void PhotosAddTags(string photoId, string tags)
 
2174
                {
 
2175
                        Hashtable parameters = new Hashtable();
 
2176
                        parameters.Add("method", "flickr.photos.addTags");
 
2177
                        parameters.Add("photo_id", photoId);
 
2178
                        parameters.Add("tags", tags);
 
2179
 
 
2180
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2181
 
 
2182
                        if( response.Status == ResponseStatus.OK )
 
2183
                        {
 
2184
                                return;
 
2185
                        }
 
2186
                        else
 
2187
                        {
 
2188
                                throw new FlickrApiException(response.Error);
 
2189
                        }
 
2190
                }
 
2191
 
 
2192
                /// <summary>
 
2193
                /// Delete a photo from Flickr.
 
2194
                /// </summary>
 
2195
                /// <remarks>
 
2196
                /// Requires Delete permissions. Also note, photos cannot be recovered once deleted.</remarks>
 
2197
                /// <param name="photoId">The ID of the photo to delete.</param>
 
2198
                public void PhotosDelete(string photoId)
 
2199
                {
 
2200
                        Hashtable parameters = new Hashtable();
 
2201
                        parameters.Add("method", "flickr.photos.delete");
 
2202
                        parameters.Add("photo_id", photoId);
 
2203
 
 
2204
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2205
 
 
2206
                        if( response.Status == ResponseStatus.OK )
 
2207
                        {
 
2208
                                return;
 
2209
                        }
 
2210
                        else
 
2211
                        {
 
2212
                                throw new FlickrApiException(response.Error);
 
2213
                        }
 
2214
                }
 
2215
 
 
2216
                /// <summary>
 
2217
                /// Get all the contexts (group, set and photostream 'next' and 'previous'
 
2218
                /// pictures) for a photo.
 
2219
                /// </summary>
 
2220
                /// <param name="photoId">The photo id of the photo to get the contexts for.</param>
 
2221
                /// <returns>An instance of the <see cref="AllContexts"/> class.</returns>
 
2222
                public AllContexts PhotosGetAllContexts(string photoId)
 
2223
                {
 
2224
                        Hashtable parameters = new Hashtable();
 
2225
                        parameters.Add("method", "flickr.photos.getAllContexts");
 
2226
                        parameters.Add("photo_id", photoId);
 
2227
 
 
2228
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2229
 
 
2230
                        if( response.Status == ResponseStatus.OK )
 
2231
                        {
 
2232
                                AllContexts contexts = new AllContexts(response.AllElements);
 
2233
                                return contexts;
 
2234
                        }
 
2235
                        else
 
2236
                        {
 
2237
                                throw new FlickrApiException(response.Error);
 
2238
                        }
 
2239
 
 
2240
                }
 
2241
 
 
2242
                /// <summary>
 
2243
                /// Gets the most recent 10 photos from your contacts.
 
2244
                /// </summary>
 
2245
                /// <returns>An instance of the <see cref="Photo"/> class containing the photos.</returns>
 
2246
                public Photos PhotosGetContactsPhotos()
 
2247
                {
 
2248
                        return PhotosGetContactsPhotos(0, false, false, false);
 
2249
                }
 
2250
 
 
2251
                /// <summary>
 
2252
                /// Gets the most recent photos from your contacts.
 
2253
                /// </summary>
 
2254
                /// <remarks>Returns the most recent photos from all your contact, excluding yourself.</remarks>
 
2255
                /// <param name="count">The number of photos to return, from between 10 and 50.</param>
 
2256
                /// <returns>An instance of the <see cref="Photo"/> class containing the photos.</returns>
 
2257
                /// <exception cref="ArgumentOutOfRangeException">
 
2258
                /// Throws a <see cref="ArgumentOutOfRangeException"/> exception if the cound
 
2259
                /// is not between 10 and 50, or 0.</exception>
 
2260
                public Photos PhotosGetContactsPhotos(long count)
 
2261
                {
 
2262
                        return PhotosGetContactsPhotos(count, false, false, false);
 
2263
                }
 
2264
 
 
2265
                /// <summary>
 
2266
                /// Gets your contacts most recent photos.
 
2267
                /// </summary>
 
2268
                /// <param name="count">The number of photos to return, from between 10 and 50.</param>
 
2269
                /// <param name="justFriends">If true only returns photos from contacts marked as
 
2270
                /// 'friends'.</param>
 
2271
                /// <param name="singlePhoto">If true only returns a single photo for each of your contacts.
 
2272
                /// Ignores the count if this is true.</param>
 
2273
                /// <param name="includeSelf">If true includes yourself in the group of people to
 
2274
                /// return photos for.</param>
 
2275
                /// <returns>An instance of the <see cref="Photo"/> class containing the photos.</returns>
 
2276
                /// <exception cref="ArgumentOutOfRangeException">
 
2277
                /// Throws a <see cref="ArgumentOutOfRangeException"/> exception if the cound
 
2278
                /// is not between 10 and 50, or 0.</exception>
 
2279
                public Photos PhotosGetContactsPhotos(long count, bool justFriends, bool singlePhoto, bool includeSelf)
 
2280
                {
 
2281
                        if( count != 0 && (count < 10 || count > 50) && !singlePhoto )
 
2282
                        {
 
2283
                                throw new ArgumentOutOfRangeException("count", String.Format("Count must be between 10 and 50. ({0})", count));
 
2284
                        }
 
2285
                        Hashtable parameters = new Hashtable();
 
2286
                        parameters.Add("method", "flickr.photos.getContactsPhotos");
 
2287
                        if( count > 0 && !singlePhoto ) parameters.Add("count", count.ToString());
 
2288
                        if( justFriends ) parameters.Add("just_friends", "1");
 
2289
                        if( singlePhoto ) parameters.Add("single_photo", "1");
 
2290
                        if( includeSelf ) parameters.Add("include_self", "1");
 
2291
 
 
2292
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2293
 
 
2294
                        if( response.Status == ResponseStatus.OK )
 
2295
                        {
 
2296
                                return response.Photos;
 
2297
                        }
 
2298
                        else
 
2299
                        {
 
2300
                                throw new FlickrApiException(response.Error);
 
2301
                        }
 
2302
                }
 
2303
 
 
2304
                /// <summary>
 
2305
                /// Gets the public photos for given users ID's contacts.
 
2306
                /// </summary>
 
2307
                /// <param name="userId">The user ID whose contacts you wish to get photos for.</param>
 
2308
                /// <returns>A <see cref="Photos"/> object containing details of the photos returned.</returns>
 
2309
                public Photos PhotosGetContactsPublicPhotos(string userId)
 
2310
                {
 
2311
                        return PhotosGetContactsPublicPhotos(userId, 0, false, false, false, PhotoSearchExtras.All);
 
2312
                }
 
2313
 
 
2314
                /// <summary>
 
2315
                /// Gets the public photos for given users ID's contacts.
 
2316
                /// </summary>
 
2317
                /// <param name="userId">The user ID whose contacts you wish to get photos for.</param>
 
2318
                /// <param name="extras">A list of extra details to return for each photo.</param>
 
2319
                /// <returns>A <see cref="Photos"/> object containing details of the photos returned.</returns>
 
2320
                public Photos PhotosGetContactsPublicPhotos(string userId, PhotoSearchExtras extras)
 
2321
                {
 
2322
                        return PhotosGetContactsPublicPhotos(userId, 0, false, false, false, extras);
 
2323
                }
 
2324
 
 
2325
                /// <summary>
 
2326
                /// Gets the public photos for given users ID's contacts.
 
2327
                /// </summary>
 
2328
                /// <param name="userId">The user ID whose contacts you wish to get photos for.</param>
 
2329
                /// <param name="count">The number of photos to return. Defaults to 10, maximum is 50.</param>
 
2330
                /// <returns>A <see cref="Photos"/> object containing details of the photos returned.</returns>
 
2331
                public Photos PhotosGetContactsPublicPhotos(string userId, long count)
 
2332
                {
 
2333
                        return PhotosGetContactsPublicPhotos(userId, count, false, false, false, PhotoSearchExtras.All);
 
2334
                }
 
2335
 
 
2336
                /// <summary>
 
2337
                /// Gets the public photos for given users ID's contacts.
 
2338
                /// </summary>
 
2339
                /// <param name="userId">The user ID whose contacts you wish to get photos for.</param>
 
2340
                /// <param name="count">The number of photos to return. Defaults to 10, maximum is 50.</param>
 
2341
                /// <param name="extras">A list of extra details to return for each photo.</param>
 
2342
                /// <returns>A <see cref="Photos"/> object containing details of the photos returned.</returns>
 
2343
                public Photos PhotosGetContactsPublicPhotos(string userId, long count, PhotoSearchExtras extras)
 
2344
                {
 
2345
                        return PhotosGetContactsPublicPhotos(userId, count, false, false, false, extras);
 
2346
                }
 
2347
 
 
2348
                /// <summary>
 
2349
                /// Gets the public photos for given users ID's contacts.
 
2350
                /// </summary>
 
2351
                /// <param name="userId">The user ID whose contacts you wish to get photos for.</param>
 
2352
                /// <param name="count">The number of photos to return. Defaults to 10, maximum is 50.</param>
 
2353
                /// <param name="justFriends">True to just return photos from friends and family (excluding regular contacts).</param>
 
2354
                /// <param name="singlePhoto">True to return just a single photo for each contact.</param>
 
2355
                /// <param name="includeSelf">True to include photos from the user ID specified as well.</param>
 
2356
                /// <returns></returns>
 
2357
                public Photos PhotosGetContactsPublicPhotos(string userId, long count, bool justFriends, bool singlePhoto, bool includeSelf)
 
2358
                {
 
2359
                        return PhotosGetContactsPublicPhotos(userId, count, justFriends, singlePhoto, includeSelf, PhotoSearchExtras.All);
 
2360
                }
 
2361
 
 
2362
                /// <summary>
 
2363
                /// Gets the public photos for given users ID's contacts.
 
2364
                /// </summary>
 
2365
                /// <param name="userId">The user ID whose contacts you wish to get photos for.</param>
 
2366
                /// <param name="count">The number of photos to return. Defaults to 10, maximum is 50.</param>
 
2367
                /// <param name="justFriends">True to just return photos from friends and family (excluding regular contacts).</param>
 
2368
                /// <param name="singlePhoto">True to return just a single photo for each contact.</param>
 
2369
                /// <param name="includeSelf">True to include photos from the user ID specified as well.</param>
 
2370
                /// <param name="extras">A list of extra details to return for each photo.</param>
 
2371
                /// <returns></returns>
 
2372
                public Photos PhotosGetContactsPublicPhotos(string userId, long count, bool justFriends, bool singlePhoto, bool includeSelf, PhotoSearchExtras extras)
 
2373
                {
 
2374
                        Hashtable parameters = new Hashtable();
 
2375
                        parameters.Add("method", "flickr.photos.getContactsPublicPhotos");
 
2376
                        parameters.Add("api_key", _apiKey);
 
2377
                        parameters.Add("user_id", userId);
 
2378
                        if( count > 0 ) parameters.Add("count", count.ToString());
 
2379
                        if( justFriends ) parameters.Add("just_friends", "1");
 
2380
                        if( singlePhoto ) parameters.Add("single_photo", "1");
 
2381
                        if( includeSelf ) parameters.Add("include_self", "1");
 
2382
                        if( extras != PhotoSearchExtras.None ) parameters.Add("extras", Utils.ExtrasToString(extras));
 
2383
 
 
2384
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2385
 
 
2386
                        if( response.Status == ResponseStatus.OK )
 
2387
                        {
 
2388
                                return response.Photos;
 
2389
                        }
 
2390
                        else
 
2391
                        {
 
2392
                                throw new FlickrApiException(response.Error);
 
2393
                        }
 
2394
                }
 
2395
 
 
2396
                /// <summary>
 
2397
                /// Gets the context of the photo in the users photostream.
 
2398
                /// </summary>
 
2399
                /// <param name="photoId">The ID of the photo to return the context for.</param>
 
2400
                /// <returns></returns>
 
2401
                public Context PhotosGetContext(string photoId)
 
2402
                {
 
2403
                        Hashtable parameters = new Hashtable();
 
2404
                        parameters.Add("method", "flickr.photos.getContext");
 
2405
                        parameters.Add("photo_id", photoId);
 
2406
 
 
2407
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2408
 
 
2409
                        if( response.Status == ResponseStatus.OK )
 
2410
                        {
 
2411
                                Context c = new Context();
 
2412
                                c.Count = response.ContextCount.Count;
 
2413
                                c.NextPhoto = response.ContextNextPhoto;
 
2414
                                c.PreviousPhoto = response.ContextPrevPhoto;
 
2415
 
 
2416
                                return c;
 
2417
                        }
 
2418
                        else
 
2419
                        {
 
2420
                                throw new FlickrApiException(response.Error);
 
2421
                        }
 
2422
                }
 
2423
 
 
2424
                /// <summary>
 
2425
                /// Returns count of photos between each pair of dates in the list.
 
2426
                /// </summary>
 
2427
                /// <remarks>If you pass in DateA, DateB and DateC it returns
 
2428
                /// a list of the number of photos between DateA and DateB,
 
2429
                /// followed by the number between DateB and DateC.
 
2430
                /// More parameters means more sets.</remarks>
 
2431
                /// <param name="dates">Array of <see cref="DateTime"/> objects.</param>
 
2432
                /// <returns><see cref="PhotoCounts"/> class instance.</returns>
 
2433
                public PhotoCounts PhotosGetCounts(DateTime[] dates)
 
2434
                {
 
2435
                        return PhotosGetCounts(dates, false);
 
2436
                }
 
2437
 
 
2438
                /// <summary>
 
2439
                /// Returns count of photos between each pair of dates in the list.
 
2440
                /// </summary>
 
2441
                /// <remarks>If you pass in DateA, DateB and DateC it returns
 
2442
                /// a list of the number of photos between DateA and DateB,
 
2443
                /// followed by the number between DateB and DateC.
 
2444
                /// More parameters means more sets.</remarks>
 
2445
                /// <param name="dates">Array of <see cref="DateTime"/> objects.</param>
 
2446
                /// <param name="taken">Boolean parameter to specify if the dates are the taken date, or uploaded date.</param>
 
2447
                /// <returns><see cref="PhotoCounts"/> class instance.</returns>
 
2448
                public PhotoCounts PhotosGetCounts(DateTime[] dates, bool taken)
 
2449
                {
 
2450
                        StringBuilder s = new StringBuilder(dates.Length * 20);
 
2451
                        foreach(DateTime d in dates)
 
2452
                        {
 
2453
                                s.Append(Utils.DateToUnixTimestamp(d));
 
2454
                                s.Append(",");
 
2455
                        }
 
2456
                        if( s.Length > 0 ) s.Remove(s.Length-2,1);
 
2457
 
 
2458
                        if( taken )
 
2459
                return PhotosGetCounts(null, s.ToString());
 
2460
                        else
 
2461
                                return PhotosGetCounts(s.ToString(), null);
 
2462
                }
 
2463
                /// <summary>
 
2464
                /// Returns count of photos between each pair of dates in the list.
 
2465
                /// </summary>
 
2466
                /// <remarks>If you pass in DateA, DateB and DateC it returns
 
2467
                /// a list of the number of photos between DateA and DateB,
 
2468
                /// followed by the number between DateB and DateC.
 
2469
                /// More parameters means more sets.</remarks>
 
2470
                /// <param name="dates">Comma-delimited list of dates in unix timestamp format. Optional.</param>
 
2471
                /// <returns><see cref="PhotoCounts"/> class instance.</returns>
 
2472
                public PhotoCounts PhotosGetCounts(string dates)
 
2473
                {
 
2474
                        return PhotosGetCounts(dates, null);
 
2475
                }
 
2476
 
 
2477
                /// <summary>
 
2478
                /// Returns count of photos between each pair of dates in the list.
 
2479
                /// </summary>
 
2480
                /// <remarks>If you pass in DateA, DateB and DateC it returns
 
2481
                /// a list of the number of photos between DateA and DateB,
 
2482
                /// followed by the number between DateB and DateC.
 
2483
                /// More parameters means more sets.</remarks>
 
2484
                /// <param name="dates">Comma-delimited list of dates in unix timestamp format. Optional.</param>
 
2485
                /// <param name="taken_dates">Comma-delimited list of dates in unix timestamp format. Optional.</param>
 
2486
                /// <returns><see cref="PhotoCounts"/> class instance.</returns>
 
2487
                public PhotoCounts PhotosGetCounts(string dates, string taken_dates)
 
2488
                {
 
2489
                        Hashtable parameters = new Hashtable();
 
2490
                        parameters.Add("method", "flickr.photos.getContactsPhotos");
 
2491
                        if( dates != null && dates.Length > 0 ) parameters.Add("dates", dates);
 
2492
                        if( taken_dates != null && taken_dates.Length > 0 ) parameters.Add("taken_dates", taken_dates);
 
2493
 
 
2494
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2495
 
 
2496
                        if( response.Status == ResponseStatus.OK )
 
2497
                        {
 
2498
                                return response.PhotoCounts;
 
2499
                        }
 
2500
                        else
 
2501
                        {
 
2502
                                throw new FlickrApiException(response.Error);
 
2503
                        }
 
2504
                }
 
2505
 
 
2506
                /// <summary>
 
2507
                /// Gets the EXIF data for a given Photo ID.
 
2508
                /// </summary>
 
2509
                /// <param name="photoId">The Photo ID of the photo to return the EXIF data for.</param>
 
2510
                /// <returns>An instance of the <see cref="ExifPhoto"/> class containing the EXIF data.</returns>
 
2511
                public ExifPhoto PhotosGetExif(string photoId)
 
2512
                {
 
2513
                        return PhotosGetExif(photoId, null);
 
2514
                }
 
2515
 
 
2516
                /// <summary>
 
2517
                /// Gets the EXIF data for a given Photo ID.
 
2518
                /// </summary>
 
2519
                /// <param name="photoId">The Photo ID of the photo to return the EXIF data for.</param>
 
2520
                /// <param name="secret">The secret of the photo. If the secret is specified then
 
2521
                /// authentication checks are bypassed.</param>
 
2522
                /// <returns>An instance of the <see cref="ExifPhoto"/> class containing the EXIF data.</returns>
 
2523
                public ExifPhoto PhotosGetExif(string photoId, string secret)
 
2524
                {
 
2525
                        Hashtable parameters = new Hashtable();
 
2526
                        parameters.Add("method", "flickr.photos.getExif");
 
2527
                        parameters.Add("photo_id", photoId);
 
2528
                        if( secret != null ) parameters.Add("secret", secret);
 
2529
 
 
2530
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2531
 
 
2532
                        if( response.Status == ResponseStatus.OK )
 
2533
                        {
 
2534
                                ExifPhoto e = new ExifPhoto(response.PhotoInfo.PhotoId,
 
2535
                                        response.PhotoInfo.Secret,
 
2536
                                        response.PhotoInfo.Server,
 
2537
                                        response.PhotoInfo.ExifTagCollection);
 
2538
 
 
2539
                                return e;
 
2540
                        }
 
2541
                        else
 
2542
                        {
 
2543
                                throw new FlickrApiException(response.Error);
 
2544
                        }
 
2545
                }
 
2546
 
 
2547
                /// <summary>
 
2548
                /// Get information about a photo. The calling user must have permission to view the photo.
 
2549
                /// </summary>
 
2550
                /// <param name="photoId">The id of the photo to fetch information for.</param>
 
2551
                /// <returns>A <see cref="PhotoInfo"/> class detailing the properties of the photo.</returns>
 
2552
                public PhotoInfo PhotosGetInfo(string photoId)
 
2553
                {
 
2554
                        return PhotosGetInfo(photoId, null);
 
2555
                }
 
2556
 
 
2557
                /// <summary>
 
2558
                /// Get information about a photo. The calling user must have permission to view the photo.
 
2559
                /// </summary>
 
2560
                /// <param name="photoId">The id of the photo to fetch information for.</param>
 
2561
                /// <param name="secret">The secret for the photo. If the correct secret is passed then permissions checking is skipped. This enables the 'sharing' of individual photos by passing around the id and secret.</param>
 
2562
                /// <returns>A <see cref="PhotoInfo"/> class detailing the properties of the photo.</returns>
 
2563
                public PhotoInfo PhotosGetInfo(string photoId, string secret)
 
2564
                {
 
2565
                        Hashtable parameters = new Hashtable();
 
2566
                        parameters.Add("method", "flickr.photos.getInfo");
 
2567
                        parameters.Add("photo_id", photoId);
 
2568
                        if( secret != null ) parameters.Add("secret", secret);
 
2569
 
 
2570
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2571
 
 
2572
                        if( response.Status == ResponseStatus.OK )
 
2573
                        {
 
2574
                                return response.PhotoInfo;
 
2575
                        }
 
2576
                        else
 
2577
                        {
 
2578
                                throw new FlickrApiException(response.Error);
 
2579
                        }
 
2580
                }
 
2581
 
 
2582
                /// <summary>
 
2583
                /// Get permissions for a photo.
 
2584
                /// </summary>
 
2585
                /// <param name="photoId">The id of the photo to get permissions for.</param>
 
2586
                /// <returns>An instance of the <see cref="PhotoPermissions"/> class containing the permissions of the specified photo.</returns>
 
2587
                public PhotoPermissions PhotosGetPerms(string photoId)
 
2588
                {
 
2589
                        Hashtable parameters = new Hashtable();
 
2590
                        parameters.Add("method", "flickr.photos.getPerms");
 
2591
                        parameters.Add("photo_id", photoId);
 
2592
 
 
2593
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2594
 
 
2595
                        if( response.Status == ResponseStatus.OK )
 
2596
                        {
 
2597
                                return new PhotoPermissions(response.AllElements[0]);
 
2598
                        }
 
2599
                        else
 
2600
                        {
 
2601
                                throw new FlickrApiException(response.Error);
 
2602
                        }
 
2603
                }
 
2604
 
 
2605
                /// <summary>
 
2606
                /// Returns a list of the latest public photos uploaded to flickr.
 
2607
                /// </summary>
 
2608
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2609
                public Photos PhotosGetRecent()
 
2610
                {
 
2611
                        return PhotosGetRecent(0, 0, PhotoSearchExtras.All);
 
2612
                }
 
2613
 
 
2614
                /// <summary>
 
2615
                /// Returns a list of the latest public photos uploaded to flickr.
 
2616
                /// </summary>
 
2617
                /// <param name="extras">A comma-delimited list of extra information to fetch for each returned record.</param>
 
2618
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2619
                public Photos PhotosGetRecent(PhotoSearchExtras extras)
 
2620
                {
 
2621
                        return PhotosGetRecent(0, 0, extras);
 
2622
                }
 
2623
 
 
2624
                /// <summary>
 
2625
                /// Returns a list of the latest public photos uploaded to flickr.
 
2626
                /// </summary>
 
2627
                /// <param name="page">The page of results to return. If this argument is omitted, it defaults to 1.</param>
 
2628
                /// <param name="perPage">Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.</param>
 
2629
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2630
                public Photos PhotosGetRecent(long perPage, long page)
 
2631
                {
 
2632
                        return PhotosGetRecent(perPage, page, PhotoSearchExtras.All);
 
2633
                }
 
2634
 
 
2635
                /// <summary>
 
2636
                /// Returns a list of the latest public photos uploaded to flickr.
 
2637
                /// </summary>
 
2638
                /// <param name="extras">A comma-delimited list of extra information to fetch for each returned record.</param>
 
2639
                /// <param name="page">The page of results to return. If this argument is omitted, it defaults to 1.</param>
 
2640
                /// <param name="perPage">Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.</param>
 
2641
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2642
                public Photos PhotosGetRecent(long perPage, long page, PhotoSearchExtras extras)
 
2643
                {
 
2644
                        Hashtable parameters = new Hashtable();
 
2645
                        parameters.Add("method", "flickr.photos.getRecent");
 
2646
                        parameters.Add("api_key", _apiKey);
 
2647
                        if( perPage > 0 ) parameters.Add("per_page", perPage.ToString());
 
2648
                        if( page > 0 ) parameters.Add("page", page.ToString());
 
2649
                        if( extras != PhotoSearchExtras.None ) parameters.Add("extras", Utils.ExtrasToString(extras));
 
2650
 
 
2651
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2652
 
 
2653
                        if( response.Status == ResponseStatus.OK )
 
2654
                        {
 
2655
                                return response.Photos;
 
2656
                        }
 
2657
                        else
 
2658
                        {
 
2659
                                throw new FlickrApiException(response.Error);
 
2660
                        }
 
2661
                }
 
2662
 
 
2663
                /// <summary>
 
2664
                /// Returns the available sizes for a photo. The calling user must have permission to view the photo.
 
2665
                /// </summary>
 
2666
                /// <param name="photoId">The id of the photo to fetch size information for.</param>
 
2667
                /// <returns>A <see cref="Sizes"/> class whose property <see cref="Sizes.SizeCollection"/> is an array of <see cref="Size"/> objects.</returns>
 
2668
                public Sizes PhotosGetSizes(string photoId)
 
2669
                {
 
2670
                        Hashtable parameters = new Hashtable();
 
2671
                        parameters.Add("method", "flickr.photos.getSizes");
 
2672
                        parameters.Add("photo_id", photoId);
 
2673
 
 
2674
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2675
 
 
2676
                        if( response.Status == ResponseStatus.OK )
 
2677
                        {
 
2678
                                return response.Sizes;
 
2679
                        }
 
2680
                        else
 
2681
                        {
 
2682
                                throw new FlickrApiException(response.Error);
 
2683
                        }
 
2684
                }
 
2685
 
 
2686
                /// <summary>
 
2687
                /// Returns a list of your photos with no tags.
 
2688
                /// </summary>
 
2689
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2690
                public Photos PhotosGetUntagged()
 
2691
                {
 
2692
                        return PhotosGetUntagged(0, 0, PhotoSearchExtras.All);
 
2693
                }
 
2694
 
 
2695
                /// <summary>
 
2696
                /// Returns a list of your photos with no tags.
 
2697
                /// </summary>
 
2698
                /// <param name="extras">A comma-delimited list of extra information to fetch for each returned record.</param>
 
2699
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2700
                public Photos PhotosGetUntagged(PhotoSearchExtras extras)
 
2701
                {
 
2702
                        return PhotosGetUntagged(0, 0, extras);
 
2703
                }
 
2704
 
 
2705
                /// <summary>
 
2706
                /// Returns a list of your photos with no tags.
 
2707
                /// </summary>
 
2708
                /// <param name="page">The page of results to return. If this argument is omitted, it defaults to 1.</param>
 
2709
                /// <param name="perPage">Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.</param>
 
2710
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2711
                public Photos PhotosGetUntagged(int perPage, int page)
 
2712
                {
 
2713
                        return PhotosGetUntagged(perPage, page, PhotoSearchExtras.All);
 
2714
                }
 
2715
 
 
2716
                /// <summary>
 
2717
                /// Returns a list of your photos with no tags.
 
2718
                /// </summary>
 
2719
                /// <param name="extras">A comma-delimited list of extra information to fetch for each returned record.</param>
 
2720
                /// <param name="page">The page of results to return. If this argument is omitted, it defaults to 1.</param>
 
2721
                /// <param name="perPage">Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.</param>
 
2722
                /// <returns>A <see cref="Photos"/> class containing the list of photos.</returns>
 
2723
                public Photos PhotosGetUntagged(int perPage, int page, PhotoSearchExtras extras)
 
2724
                {
 
2725
                        Hashtable parameters = new Hashtable();
 
2726
                        parameters.Add("method", "flickr.photos.getUntagged");
 
2727
                        if( perPage > 0 ) parameters.Add("per_page", perPage.ToString());
 
2728
                        if( page > 0 ) parameters.Add("page", page.ToString());
 
2729
                        if( extras != PhotoSearchExtras.None ) parameters.Add("extras", Utils.ExtrasToString(extras));
 
2730
 
 
2731
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2732
 
 
2733
                        if( response.Status == ResponseStatus.OK )
 
2734
                        {
 
2735
                                return response.Photos;
 
2736
                        }
 
2737
                        else
 
2738
                        {
 
2739
                                throw new FlickrApiException(response.Error);
 
2740
                        }
 
2741
                }
 
2742
 
 
2743
                /// <summary>
 
2744
                /// Gets a list of photos not in sets. Defaults to include all extra fields.
 
2745
                /// </summary>
 
2746
                /// <returns><see cref="Photos"/> instance containing list of photos.</returns>
 
2747
                public Photos PhotosGetNotInSet()
 
2748
                {
 
2749
                        return PhotosGetNotInSet(new PartialSearchOptions());
 
2750
                }
 
2751
 
 
2752
                /// <summary>
 
2753
                /// Gets a specific page of the list of photos which are not in sets.
 
2754
                /// Defaults to include all extra fields.
 
2755
                /// </summary>
 
2756
                /// <param name="page">The page number to return.</param>
 
2757
                /// <returns><see cref="Photos"/> instance containing list of photos.</returns>
 
2758
                public Photos PhotosGetNotInSet(int page)
 
2759
                {
 
2760
                        return PhotosGetNotInSet(0, page, PhotoSearchExtras.None);
 
2761
                }
 
2762
 
 
2763
                /// <summary>
 
2764
                /// Gets a specific page of the list of photos which are not in sets.
 
2765
                /// Defaults to include all extra fields.
 
2766
                /// </summary>
 
2767
                /// <param name="perPage">Number of photos per page.</param>
 
2768
                /// <param name="page">The page number to return.</param>
 
2769
                /// <returns><see cref="Photos"/> instance containing list of photos.</returns>
 
2770
                public Photos PhotosGetNotInSet(int perPage, int page)
 
2771
                {
 
2772
                        return PhotosGetNotInSet(perPage, page, PhotoSearchExtras.None);
 
2773
                }
 
2774
 
 
2775
                /// <summary>
 
2776
                /// Gets a list of a users photos which are not in a set.
 
2777
                /// </summary>
 
2778
                /// <param name="perPage">Number of photos per page.</param>
 
2779
                /// <param name="page">The page number to return.</param>
 
2780
                /// <param name="extras"><see cref="PhotoSearchExtras"/> enumeration.</param>
 
2781
                /// <returns><see cref="Photos"/> instance containing list of photos.</returns>
 
2782
                public Photos PhotosGetNotInSet(int perPage, int page, PhotoSearchExtras extras)
 
2783
                {
 
2784
                        PartialSearchOptions options = new PartialSearchOptions();
 
2785
                        options.PerPage = perPage;
 
2786
                        options.Page = page;
 
2787
                        options.Extras = extras;
 
2788
 
 
2789
                        return PhotosGetNotInSet(options);
 
2790
                }
 
2791
 
 
2792
                /// <summary>
 
2793
                /// Gets a list of the authenticated users photos which are not in a set.
 
2794
                /// </summary>
 
2795
                /// <param name="options">A selection of options to filter/sort by.</param>
 
2796
                /// <returns>A collection of photos in the <see cref="Photos"/> class.</returns>
 
2797
                public Photos PhotosGetNotInSet(PartialSearchOptions options)
 
2798
                {
 
2799
                        Hashtable parameters = new Hashtable();
 
2800
                        parameters.Add("method", "flickr.photos.getNotInSet");
 
2801
                        Utils.PartialOptionsIntoArray(options, parameters);
 
2802
 
 
2803
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2804
 
 
2805
                        if( response.Status == ResponseStatus.OK )
 
2806
                        {
 
2807
                                return response.Photos;
 
2808
                        }
 
2809
                        else
 
2810
                        {
 
2811
                                throw new FlickrApiException(response.Error);
 
2812
                        }
 
2813
                }
 
2814
 
 
2815
                /// <summary>
 
2816
                /// Gets a list of all current licenses.
 
2817
                /// </summary>
 
2818
                /// <returns><see cref="Licenses"/> instance.</returns>
 
2819
                public Licenses PhotosLicensesGetInfo()
 
2820
                {
 
2821
                        Hashtable parameters = new Hashtable();
 
2822
                        parameters.Add("method", "flickr.photos.licenses.getInfo");
 
2823
                        parameters.Add("api_key", _apiKey);
 
2824
 
 
2825
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2826
 
 
2827
                        if( response.Status == ResponseStatus.OK )
 
2828
                        {
 
2829
                                return response.Licenses;
 
2830
                        }
 
2831
                        else
 
2832
                        {
 
2833
                                throw new FlickrApiException(response.Error);
 
2834
                        }
 
2835
                }
 
2836
 
 
2837
                /// <summary>
 
2838
                /// Remove an existing tag.
 
2839
                /// </summary>
 
2840
                /// <param name="tagId">The id of the tag, as returned by <see cref="Flickr.PhotosGetInfo(string)"/> or similar method.</param>
 
2841
                /// <returns>True if the tag was removed.</returns>
 
2842
                public bool PhotosRemoveTag(string tagId)
 
2843
                {
 
2844
                        Hashtable parameters = new Hashtable();
 
2845
                        parameters.Add("method", "flickr.photos.removeTag");
 
2846
                        parameters.Add("tag_id", tagId);
 
2847
 
 
2848
                        FlickrNet.Response response = GetResponseCache(parameters);
 
2849
 
 
2850
                        if( response.Status == ResponseStatus.OK )
 
2851
                        {
 
2852
                                return true;
 
2853
                        }
 
2854
                        else
 
2855
                        {
 
2856
                                throw new FlickrApiException(response.Error);
 
2857
                        }
 
2858
                }
 
2859
 
 
2860
                /// <summary>
 
2861
                /// Search for photos containing text, rather than tags.
 
2862
                /// </summary>
 
2863
                /// <param name="userId">The user whose photos you wish to search for.</param>
 
2864
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2865
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2866
                public Photos PhotosSearchText(string userId, string text)
 
2867
                {
 
2868
                        return PhotosSearch(userId, "", 0, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
2869
                }
 
2870
 
 
2871
                /// <summary>
 
2872
                /// Search for photos containing text, rather than tags.
 
2873
                /// </summary>
 
2874
                /// <param name="userId">The user whose photos you wish to search for.</param>
 
2875
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2876
                /// <param name="extras">Optional extras to return.</param>
 
2877
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2878
                public Photos PhotosSearchText(string userId, string text, PhotoSearchExtras extras)
 
2879
                {
 
2880
                        return PhotosSearch(userId, "", 0, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
2881
                }
 
2882
 
 
2883
                /// <summary>
 
2884
                /// Search for photos containing text, rather than tags.
 
2885
                /// </summary>
 
2886
                /// <param name="userId">The user whose photos you wish to search for.</param>
 
2887
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2888
                /// <param name="license">The license type to return.</param>
 
2889
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2890
                public Photos PhotosSearchText(string userId, string text, int license)
 
2891
                {
 
2892
                        return PhotosSearch(userId, "", 0, text, DateTime.MinValue, DateTime.MinValue, license, 0, 0, PhotoSearchExtras.All);
 
2893
                }
 
2894
 
 
2895
                /// <summary>
 
2896
                /// Search for photos containing text, rather than tags.
 
2897
                /// </summary>
 
2898
                /// <param name="userId">The user whose photos you wish to search for.</param>
 
2899
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2900
                /// <param name="license">The license type to return.</param>
 
2901
                /// <param name="extras">Optional extras to return.</param>
 
2902
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2903
                public Photos PhotosSearchText(string userId, string text, int license, PhotoSearchExtras extras)
 
2904
                {
 
2905
                        return PhotosSearch(userId, "", 0, text, DateTime.MinValue, DateTime.MinValue, license, 0, 0, extras);
 
2906
                }
 
2907
 
 
2908
                /// <summary>
 
2909
                /// Search for photos containing text, rather than tags.
 
2910
                /// </summary>
 
2911
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2912
                /// <param name="extras">Optional extras to return.</param>
 
2913
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2914
                public Photos PhotosSearchText(string text, PhotoSearchExtras extras)
 
2915
                {
 
2916
                        return PhotosSearch(null, "", 0, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
2917
                }
 
2918
 
 
2919
                /// <summary>
 
2920
                /// Search for photos containing text, rather than tags.
 
2921
                /// </summary>
 
2922
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2923
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2924
                public Photos PhotosSearchText(string text)
 
2925
                {
 
2926
                        return PhotosSearch(null, "", 0, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
2927
                }
 
2928
 
 
2929
                /// <summary>
 
2930
                /// Search for photos containing text, rather than tags.
 
2931
                /// </summary>
 
2932
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2933
                /// <param name="license">The license type to return.</param>
 
2934
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2935
                public Photos PhotosSearchText(string text, int license)
 
2936
                {
 
2937
                        return PhotosSearch(null, "", 0, text, DateTime.MinValue, DateTime.MinValue, license, 0, 0, PhotoSearchExtras.All);
 
2938
                }
 
2939
 
 
2940
                /// <summary>
 
2941
                /// Search for photos containing text, rather than tags.
 
2942
                /// </summary>
 
2943
                /// <param name="text">The text you want to search for in titles and descriptions.</param>
 
2944
                /// <param name="license">The license type to return.</param>
 
2945
                /// <param name="extras">Optional extras to return.</param>
 
2946
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2947
                public Photos PhotosSearchText(string text, int license, PhotoSearchExtras extras)
 
2948
                {
 
2949
                        return PhotosSearch(null, "", 0, text, DateTime.MinValue, DateTime.MinValue, license, 0, 0, extras);
 
2950
                }
 
2951
 
 
2952
                /// <summary>
 
2953
                /// Search for photos containing an array of tags.
 
2954
                /// </summary>
 
2955
                /// <param name="tags">An array of tags to search for.</param>
 
2956
                /// <param name="extras">Optional extras to return.</param>
 
2957
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2958
                public Photos PhotosSearch(string[] tags, PhotoSearchExtras extras)
 
2959
                {
 
2960
                        return PhotosSearch(null, tags, 0, "", DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
2961
                }
 
2962
 
 
2963
                /// <summary>
 
2964
                /// Search for photos containing an array of tags.
 
2965
                /// </summary>
 
2966
                /// <param name="tags">An array of tags to search for.</param>
 
2967
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2968
                public Photos PhotosSearch(string[] tags)
 
2969
                {
 
2970
                        return PhotosSearch(null, tags, 0, "", DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
2971
                }
 
2972
 
 
2973
                /// <summary>
 
2974
                /// Search for photos containing an array of tags.
 
2975
                /// </summary>
 
2976
                /// <param name="tags">An array of tags to search for.</param>
 
2977
                /// <param name="license">The license type to return.</param>
 
2978
                /// <param name="extras">Optional extras to return.</param>
 
2979
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2980
                public Photos PhotosSearch(string[] tags, int license, PhotoSearchExtras extras)
 
2981
                {
 
2982
                        return PhotosSearch(null, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, extras);
 
2983
                }
 
2984
 
 
2985
                /// <summary>
 
2986
                /// Search for photos containing an array of tags.
 
2987
                /// </summary>
 
2988
                /// <param name="tags">An array of tags to search for.</param>
 
2989
                /// <param name="license">The license type to return.</param>
 
2990
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
2991
                public Photos PhotosSearch(string[] tags, int license)
 
2992
                {
 
2993
                        return PhotosSearch(null, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, PhotoSearchExtras.All);
 
2994
                }
 
2995
 
 
2996
                /// <summary>
 
2997
                /// Search for photos.
 
2998
                /// </summary>
 
2999
                /// <param name="tags">An array of tags to search for.</param>
 
3000
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3001
                /// <param name="text">Text to search for in photo title or description.</param>
 
3002
                /// <param name="perPage">Number of photos to return per page.</param>
 
3003
                /// <param name="page">The page number to return.</param>
 
3004
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3005
                public Photos PhotosSearch(string[] tags, TagMode tagMode, string text, int perPage, int page)
 
3006
                {
 
3007
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, PhotoSearchExtras.All);
 
3008
                }
 
3009
 
 
3010
                /// <summary>
 
3011
                /// Search for photos.
 
3012
                /// </summary>
 
3013
                /// <param name="tags">An array of tags to search for.</param>
 
3014
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3015
                /// <param name="text">Text to search for in photo title or description.</param>
 
3016
                /// <param name="perPage">Number of photos to return per page.</param>
 
3017
                /// <param name="page">The page number to return.</param>
 
3018
                /// <param name="extras">Optional extras to return.</param>
 
3019
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3020
                public Photos PhotosSearch(string[] tags, TagMode tagMode, string text, int perPage, int page, PhotoSearchExtras extras)
 
3021
                {
 
3022
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, extras);
 
3023
                }
 
3024
 
 
3025
                /// <summary>
 
3026
                /// Search for photos.
 
3027
                /// </summary>
 
3028
                /// <param name="tags">An array of tags to search for.</param>
 
3029
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3030
                /// <param name="text">Text to search for in photo title or description.</param>
 
3031
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3032
                public Photos PhotosSearch(string[] tags, TagMode tagMode, string text)
 
3033
                {
 
3034
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
3035
                }
 
3036
 
 
3037
                /// <summary>
 
3038
                /// Search for photos.
 
3039
                /// </summary>
 
3040
                /// <param name="tags">An array of tags to search for.</param>
 
3041
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3042
                /// <param name="text">Text to search for in photo title or description.</param>
 
3043
                /// <param name="extras">Optional extras to return.</param>
 
3044
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3045
                public Photos PhotosSearch(string[] tags, TagMode tagMode, string text, PhotoSearchExtras extras)
 
3046
                {
 
3047
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
3048
                }
 
3049
 
 
3050
                /// <summary>
 
3051
                /// Search for photos.
 
3052
                /// </summary>
 
3053
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3054
                /// <param name="tags">An array of tags to search for.</param>
 
3055
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3056
                public Photos PhotosSearch(string userId, string[] tags)
 
3057
                {
 
3058
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
3059
                }
 
3060
 
 
3061
                /// <summary>
 
3062
                /// Search for photos.
 
3063
                /// </summary>
 
3064
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3065
                /// <param name="tags">An array of tags to search for.</param>
 
3066
                /// <param name="extras">Optional extras to return.</param>
 
3067
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3068
                public Photos PhotosSearch(string userId, string[] tags, PhotoSearchExtras extras)
 
3069
                {
 
3070
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
3071
                }
 
3072
 
 
3073
                /// <summary>
 
3074
                /// Search for photos.
 
3075
                /// </summary>
 
3076
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3077
                /// <param name="tags">An array of tags to search for.</param>
 
3078
                /// <param name="license">The license type to return.</param>
 
3079
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3080
                public Photos PhotosSearch(string userId, string[] tags, int license)
 
3081
                {
 
3082
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, PhotoSearchExtras.All);
 
3083
                }
 
3084
 
 
3085
                /// <summary>
 
3086
                /// Search for photos.
 
3087
                /// </summary>
 
3088
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3089
                /// <param name="tags">An array of tags to search for.</param>
 
3090
                /// <param name="license">The license type to return.</param>
 
3091
                /// <param name="extras">Optional extras to return.</param>
 
3092
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3093
                public Photos PhotosSearch(string userId, string[] tags, int license, PhotoSearchExtras extras)
 
3094
                {
 
3095
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, extras);
 
3096
                }
 
3097
 
 
3098
                /// <summary>
 
3099
                /// Search for photos.
 
3100
                /// </summary>
 
3101
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3102
                /// <param name="tags">An array of tags to search for.</param>
 
3103
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3104
                /// <param name="text">Text to search for in photo title or description.</param>
 
3105
                /// <param name="perPage">Number of photos to return per page.</param>
 
3106
                /// <param name="page">The page number to return.</param>
 
3107
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3108
                public Photos PhotosSearch(string userId, string[] tags, TagMode tagMode, string text, int perPage, int page)
 
3109
                {
 
3110
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, PhotoSearchExtras.All);
 
3111
                }
 
3112
 
 
3113
                /// <summary>
 
3114
                /// Search for photos.
 
3115
                /// </summary>
 
3116
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3117
                /// <param name="tags">An array of tags to search for.</param>
 
3118
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3119
                /// <param name="text">Text to search for in photo title or description.</param>
 
3120
                /// <param name="perPage">Number of photos to return per page.</param>
 
3121
                /// <param name="page">The page number to return.</param>
 
3122
                /// <param name="extras">Optional extras to return.</param>
 
3123
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3124
                public Photos PhotosSearch(string userId, string[] tags, TagMode tagMode, string text, int perPage, int page, PhotoSearchExtras extras)
 
3125
                {
 
3126
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, extras);
 
3127
                }
 
3128
 
 
3129
                /// <summary>
 
3130
                /// Search for photos.
 
3131
                /// </summary>
 
3132
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3133
                /// <param name="tags">An array of tags to search for.</param>
 
3134
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3135
                /// <param name="text">Text to search for in photo title or description.</param>
 
3136
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3137
                public Photos PhotosSearch(string userId, string[] tags, TagMode tagMode, string text)
 
3138
                {
 
3139
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
3140
                }
 
3141
 
 
3142
                /// <summary>
 
3143
                /// Search for photos.
 
3144
                /// </summary>
 
3145
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3146
                /// <param name="tags">An array of tags to search for.</param>
 
3147
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3148
                /// <param name="text">Text to search for in photo title or description.</param>
 
3149
                /// <param name="extras">Optional extras to return.</param>
 
3150
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3151
                public Photos PhotosSearch(string userId, string[] tags, TagMode tagMode, string text, PhotoSearchExtras extras)
 
3152
                {
 
3153
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
3154
                }
 
3155
 
 
3156
                /// <summary>
 
3157
                /// Search for photos.
 
3158
                /// </summary>
 
3159
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3160
                /// <param name="tags">An array of tags to search for.</param>
 
3161
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3162
                /// <param name="text">Text to search for in photo title or description.</param>
 
3163
                /// <param name="minUploadDate">The minimum upload date.</param>
 
3164
                /// <param name="maxUploadDate">The maxmimum upload date.</param>
 
3165
                /// <param name="license">The license type to return.</param>
 
3166
                /// <param name="perPage">Number of photos to return per page.</param>
 
3167
                /// <param name="page">The page number to return.</param>
 
3168
                /// <param name="extras">Optional extras to return.</param>
 
3169
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3170
                public Photos PhotosSearch(string userId, string[] tags, TagMode tagMode, string text, DateTime minUploadDate, DateTime maxUploadDate, int license, int perPage, int page, PhotoSearchExtras extras)
 
3171
                {
 
3172
                        return PhotosSearch(userId, String.Join(",", tags), tagMode, text, minUploadDate, maxUploadDate, license, perPage, page, extras);
 
3173
                }
 
3174
 
 
3175
                /// <summary>
 
3176
                /// Search for photos.
 
3177
                /// </summary>
 
3178
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3179
                /// <param name="tags">An array of tags to search for.</param>
 
3180
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3181
                /// <param name="text">Text to search for in photo title or description.</param>
 
3182
                /// <param name="minUploadDate">The minimum upload date.</param>
 
3183
                /// <param name="maxUploadDate">The maxmimum upload date.</param>
 
3184
                /// <param name="license">The license type to return.</param>
 
3185
                /// <param name="perPage">Number of photos to return per page.</param>
 
3186
                /// <param name="page">The page number to return.</param>
 
3187
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3188
                public Photos PhotosSearch(string userId, string[] tags, TagMode tagMode, string text, DateTime minUploadDate, DateTime maxUploadDate, int license, int perPage, int page)
 
3189
                {
 
3190
                        return PhotosSearch(userId, String.Join(",", tags), tagMode, text, minUploadDate, maxUploadDate, license, perPage, page, PhotoSearchExtras.All);
 
3191
                }
 
3192
 
 
3193
                // PhotoSearch - tags versions
 
3194
 
 
3195
                /// <summary>
 
3196
                /// Search for photos.
 
3197
                /// </summary>
 
3198
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3199
                /// <param name="license">The license type to return.</param>
 
3200
                /// <param name="extras">Optional extras to return.</param>
 
3201
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3202
                public Photos PhotosSearch(string tags, int license, PhotoSearchExtras extras)
 
3203
                {
 
3204
                        return PhotosSearch(null, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, extras);
 
3205
                }
 
3206
 
 
3207
                /// <summary>
 
3208
                /// Search for photos.
 
3209
                /// </summary>
 
3210
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3211
                /// <param name="license">The license type to return.</param>
 
3212
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3213
                public Photos PhotosSearch(string tags, int license)
 
3214
                {
 
3215
                        return PhotosSearch(null, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, PhotoSearchExtras.All);
 
3216
                }
 
3217
 
 
3218
                /// <summary>
 
3219
                /// Search for photos.
 
3220
                /// </summary>
 
3221
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3222
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3223
                /// <param name="text">Text to search for in photo title or description.</param>
 
3224
                /// <param name="perPage">Number of photos to return per page.</param>
 
3225
                /// <param name="page">The page number to return.</param>
 
3226
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3227
                public Photos PhotosSearch(string tags, TagMode tagMode, string text, int perPage, int page)
 
3228
                {
 
3229
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, PhotoSearchExtras.All);
 
3230
                }
 
3231
 
 
3232
                /// <summary>
 
3233
                /// Search for photos.
 
3234
                /// </summary>
 
3235
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3236
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3237
                /// <param name="text">Text to search for in photo title or description.</param>
 
3238
                /// <param name="perPage">Number of photos to return per page.</param>
 
3239
                /// <param name="page">The page number to return.</param>
 
3240
                /// <param name="extras">Optional extras to return.</param>
 
3241
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3242
                public Photos PhotosSearch(string tags, TagMode tagMode, string text, int perPage, int page, PhotoSearchExtras extras)
 
3243
                {
 
3244
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, extras);
 
3245
                }
 
3246
 
 
3247
                /// <summary>
 
3248
                /// Search for photos.
 
3249
                /// </summary>
 
3250
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3251
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3252
                /// <param name="text">Text to search for in photo title or description.</param>
 
3253
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3254
                public Photos PhotosSearch(string tags, TagMode tagMode, string text)
 
3255
                {
 
3256
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
3257
                }
 
3258
 
 
3259
                /// <summary>
 
3260
                /// Search for photos.
 
3261
                /// </summary>
 
3262
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3263
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3264
                /// <param name="text">Text to search for in photo title or description.</param>
 
3265
                /// <param name="extras">Optional extras to return.</param>
 
3266
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3267
                public Photos PhotosSearch(string tags, TagMode tagMode, string text, PhotoSearchExtras extras)
 
3268
                {
 
3269
                        return PhotosSearch(null, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
3270
                }
 
3271
 
 
3272
                /// <summary>
 
3273
                /// Search for photos.
 
3274
                /// </summary>
 
3275
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3276
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3277
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3278
                public Photos PhotosSearch(string userId, string tags)
 
3279
                {
 
3280
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
3281
                }
 
3282
 
 
3283
                /// <summary>
 
3284
                /// Search for photos.
 
3285
                /// </summary>
 
3286
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3287
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3288
                /// <param name="extras">Optional extras to return.</param>
 
3289
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3290
                public Photos PhotosSearch(string userId, string tags, PhotoSearchExtras extras)
 
3291
                {
 
3292
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
3293
                }
 
3294
 
 
3295
                /// <summary>
 
3296
                /// Search for photos.
 
3297
                /// </summary>
 
3298
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3299
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3300
                /// <param name="license">The license type to return.</param>
 
3301
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3302
                public Photos PhotosSearch(string userId, string tags, int license)
 
3303
                {
 
3304
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, PhotoSearchExtras.All);
 
3305
                }
 
3306
 
 
3307
                /// <summary>
 
3308
                /// Search for photos.
 
3309
                /// </summary>
 
3310
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3311
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3312
                /// <param name="license">The license type to return.</param>
 
3313
                /// <param name="extras">Optional extras to return.</param>
 
3314
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3315
                public Photos PhotosSearch(string userId, string tags, int license, PhotoSearchExtras extras)
 
3316
                {
 
3317
                        return PhotosSearch(userId, tags, 0, "", DateTime.MinValue, DateTime.MinValue, license, 0, 0, extras);
 
3318
                }
 
3319
 
 
3320
                /// <summary>
 
3321
                /// Search for photos.
 
3322
                /// </summary>
 
3323
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3324
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3325
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3326
                /// <param name="text">Text to search for in photo title or description.</param>
 
3327
                /// <param name="perPage">Number of photos to return per page.</param>
 
3328
                /// <param name="page">The page number to return.</param>
 
3329
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3330
                public Photos PhotosSearch(string userId, string tags, TagMode tagMode, string text, int perPage, int page)
 
3331
                {
 
3332
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, PhotoSearchExtras.All);
 
3333
                }
 
3334
 
 
3335
                /// <summary>
 
3336
                /// Search for photos.
 
3337
                /// </summary>
 
3338
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3339
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3340
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3341
                /// <param name="text">Text to search for in photo title or description.</param>
 
3342
                /// <param name="perPage">Number of photos to return per page.</param>
 
3343
                /// <param name="page">The page number to return.</param>
 
3344
                /// <param name="extras">Optional extras to return.</param>
 
3345
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3346
                public Photos PhotosSearch(string userId, string tags, TagMode tagMode, string text, int perPage, int page, PhotoSearchExtras extras)
 
3347
                {
 
3348
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, perPage, page, extras);
 
3349
                }
 
3350
 
 
3351
                /// <summary>
 
3352
                /// Search for photos.
 
3353
                /// </summary>
 
3354
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3355
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3356
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3357
                /// <param name="text">Text to search for in photo title or description.</param>
 
3358
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3359
                public Photos PhotosSearch(string userId, string tags, TagMode tagMode, string text)
 
3360
                {
 
3361
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, PhotoSearchExtras.All);
 
3362
                }
 
3363
 
 
3364
                /// <summary>
 
3365
                /// Search for photos.
 
3366
                /// </summary>
 
3367
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3368
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3369
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3370
                /// <param name="text">Text to search for in photo title or description.</param>
 
3371
                /// <param name="extras">Optional extras to return.</param>
 
3372
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3373
                public Photos PhotosSearch(string userId, string tags, TagMode tagMode, string text, PhotoSearchExtras extras)
 
3374
                {
 
3375
                        return PhotosSearch(userId, tags, tagMode, text, DateTime.MinValue, DateTime.MinValue, 0, 0, 0, extras);
 
3376
                }
 
3377
 
 
3378
                // Actual PhotoSearch function
 
3379
 
 
3380
                /// <summary>
 
3381
                /// Search for photos.
 
3382
                /// </summary>
 
3383
                /// <param name="userId">The ID of the user to search the photos of.</param>
 
3384
                /// <param name="tags">A comma seperated list of tags to search for.</param>
 
3385
                /// <param name="tagMode">Match all tags, or any tag.</param>
 
3386
                /// <param name="text">Text to search for in photo title or description.</param>
 
3387
                /// <param name="perPage">Number of photos to return per page.</param>
 
3388
                /// <param name="page">The page number to return.</param>
 
3389
                /// <param name="extras">Optional extras to return.</param>
 
3390
                /// <param name="minUploadDate">The minimum upload date.</param>
 
3391
                /// <param name="maxUploadDate">The maxmimum upload date.</param>
 
3392
                /// <param name="license">The license type to return.</param>
 
3393
                /// <returns>A <see cref="Photos"/> instance.</returns>
 
3394
                public Photos PhotosSearch(string userId, string tags, TagMode tagMode, string text, DateTime minUploadDate, DateTime maxUploadDate, int license, int perPage, int page, PhotoSearchExtras extras)
 
3395
                {
 
3396
                        PhotoSearchOptions options = new PhotoSearchOptions();
 
3397
                        options.UserId = userId;
 
3398
                        options.Tags = tags;
 
3399
                        options.TagMode = tagMode;
 
3400
                        options.Text = text;
 
3401
                        options.MinUploadDate = minUploadDate;
 
3402
                        options.MaxUploadDate = maxUploadDate;
 
3403
                        if( license > 0 ) options.AddLicense(license);
 
3404
                        options.PerPage = perPage;
 
3405
                        options.Page = page;
 
3406
                        options.Extras = extras;
 
3407
 
 
3408
                        return PhotosSearch(options);
 
3409
                }
 
3410
 
 
3411
                /// <summary>
 
3412
                /// Search for a set of photos, based on the value of the <see cref="PhotoSearchOptions"/> parameters.
 
3413
                /// </summary>
 
3414
                /// <param name="options">The parameters to search for.</param>
 
3415
                /// <returns>A collection of photos contained within a <see cref="Photos"/> object.</returns>
 
3416
                public Photos PhotosSearch(PhotoSearchOptions options)
 
3417
                {
 
3418
                        Hashtable parameters = new Hashtable();
 
3419
                        parameters.Add("method", "flickr.photos.search");
 
3420
                        if( options.UserId != null && options.UserId.Length > 0 ) parameters.Add("user_id", options.UserId);
 
3421
                        if( options.Text != null && options.Text.Length > 0 ) parameters.Add("text", options.Text);
 
3422
                        if( options.Tags != null && options.Tags.Length > 0 ) parameters.Add("tags", options.Tags);
 
3423
                        if( options.TagMode != TagMode.None ) parameters.Add("tag_mode", options.TagModeString);
 
3424
                        if( options.MachineTags != null && options.MachineTags.Length > 0 ) parameters.Add("machine_tags", options.MachineTags);
 
3425
                        if( options.MachineTagMode != MachineTagMode.None ) parameters.Add("machine_tag_mode", options.MachineTagModeString);
 
3426
                        if( options.MinUploadDate != DateTime.MinValue ) parameters.Add("min_upload_date", Utils.DateToUnixTimestamp(options.MinUploadDate).ToString());
 
3427
                        if( options.MaxUploadDate != DateTime.MinValue ) parameters.Add("max_upload_date", Utils.DateToUnixTimestamp(options.MaxUploadDate).ToString());
 
3428
                        if( options.MinTakenDate != DateTime.MinValue ) parameters.Add("min_taken_date", options.MinTakenDate.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo));
 
3429
                        if( options.MaxTakenDate != DateTime.MinValue ) parameters.Add("max_taken_date", options.MaxTakenDate.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo));
 
3430
                        if( options.Licenses.Length != 0 )
 
3431
                        {
 
3432
                                string lic = "";
 
3433
                                for(int i = 0; i < options.Licenses.Length; i++)
 
3434
                                {
 
3435
                                        if( i > 0 ) lic += ",";
 
3436
                                        lic += Convert.ToString(options.Licenses[i]);
 
3437
                                }
 
3438
                                parameters.Add("license", lic);
 
3439
                        }
 
3440
                        if( options.PerPage != 0 ) parameters.Add("per_page", options.PerPage.ToString());
 
3441
                        if( options.Page != 0 ) parameters.Add("page", options.Page.ToString());
 
3442
                        if( options.Extras != PhotoSearchExtras.None ) parameters.Add("extras", options.ExtrasString);
 
3443
                        if( options.SortOrder != PhotoSearchSortOrder.None ) parameters.Add("sort", options.SortOrderString);
 
3444
                        if( options.PrivacyFilter != PrivacyFilter.None ) parameters.Add("privacy_filter", options.PrivacyFilter.ToString("d"));
 
3445
                        if( options.BoundaryBox.IsSet ) parameters.Add("bbox", options.BoundaryBox.ToString());
 
3446
                        if( options.Accuracy != GeoAccuracy.None ) parameters.Add("accuracy", options.Accuracy.ToString("d"));
 
3447
 
 
3448
                        FlickrNet.Response response = GetResponseCache(parameters);
 
3449
 
 
3450
                        if( response.Status == ResponseStatus.OK )
 
3451
                        {
 
3452
                                return response.Photos;
 
3453
                        }
 
3454
                        else
 
3455
                        {
 
3456
                                throw new FlickrApiException(response.Error);
 
3457
                        }
 
3458
                }
 
3459
 
 
3460
                /// <summary>
 
3461
                /// Set the date taken for a photo.
 
3462
                /// </summary>
 
3463
                /// <remarks>
 
3464
                /// All dates are assumed to be GMT. It is the developers responsibility to change dates to the local users
 
3465
                /// timezone.
 
3466
                /// </remarks>
 
3467
                /// <param name="photoId">The id of the photo to set the date taken for.</param>
 
3468
                /// <param name="dateTaken">The date taken.</param>
 
3469
                /// <param name="granularity">The granularity of the date taken.</param>
 
3470
                /// <returns>True if the date was updated successfully.</returns>
 
3471
                public bool PhotosSetDates(string photoId, DateTime dateTaken, DateGranularity granularity)
 
3472
                {
 
3473
                        return PhotosSetDates(photoId, DateTime.MinValue, dateTaken, granularity);
 
3474
                }
 
3475
 
 
3476
                /// <summary>
 
3477
                /// Set the date the photo was posted (uploaded). This will affect the order in which photos
 
3478
                /// are seen in your photostream.
 
3479
                /// </summary>
 
3480
                /// <remarks>
 
3481
                /// All dates are assumed to be GMT. It is the developers responsibility to change dates to the local users
 
3482
                /// timezone.
 
3483
                /// </remarks>
 
3484
                /// <param name="photoId">The id of the photo to set the date posted.</param>
 
3485
                /// <param name="datePosted">The new date to set the date posted too.</param>
 
3486
                /// <returns>True if the date was updated successfully.</returns>
 
3487
                public bool PhotosSetDates(string photoId, DateTime datePosted)
 
3488
                {
 
3489
                        return PhotosSetDates(photoId, datePosted, DateTime.MinValue, DateGranularity.FullDate);
 
3490
                }
 
3491
 
 
3492
                /// <summary>
 
3493
                /// Set the date the photo was posted (uploaded) and the date the photo was taken.
 
3494
                /// Changing the date posted will affect the order in which photos are seen in your photostream.
 
3495
                /// </summary>
 
3496
                /// <remarks>
 
3497
                /// All dates are assumed to be GMT. It is the developers responsibility to change dates to the local users
 
3498
                /// timezone.
 
3499
                /// </remarks>
 
3500
                /// <param name="photoId">The id of the photo to set the dates.</param>
 
3501
                /// <param name="datePosted">The new date to set the date posted too.</param>
 
3502
                /// <param name="dateTaken">The new date to set the date taken too.</param>
 
3503
                /// <param name="granularity">The granularity of the date taken.</param>
 
3504
                /// <returns>True if the dates where updated successfully.</returns>
 
3505
                public bool PhotosSetDates(string photoId, DateTime datePosted, DateTime dateTaken, DateGranularity granularity)
 
3506
                {
 
3507
                        Hashtable parameters = new Hashtable();
 
3508
                        parameters.Add("method", "flickr.photos.setDates");
 
3509
                        parameters.Add("photo_id", photoId);
 
3510
                        if( datePosted != DateTime.MinValue ) parameters.Add("date_posted", Utils.DateToUnixTimestamp(datePosted).ToString());
 
3511
                        if( dateTaken != DateTime.MinValue )
 
3512
                        {
 
3513
                                parameters.Add("date_taken", dateTaken.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo));
 
3514
                                parameters.Add("date_taken_granularity", granularity.ToString("d"));
 
3515
                        }
 
3516
 
 
3517
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3518
 
 
3519
                        if( response.Status == ResponseStatus.OK )
 
3520
                        {
 
3521
                                return true;
 
3522
                        }
 
3523
                        else
 
3524
                        {
 
3525
                                throw new FlickrApiException(response.Error);
 
3526
                        }
 
3527
 
 
3528
                }
 
3529
 
 
3530
                /// <summary>
 
3531
                /// Sets the title and description of the photograph.
 
3532
                /// </summary>
 
3533
                /// <param name="photoId">The numerical photoId of the photograph.</param>
 
3534
                /// <param name="title">The new title of the photograph.</param>
 
3535
                /// <param name="description">The new description of the photograph.</param>
 
3536
                /// <returns>True when the operation is successful.</returns>
 
3537
                /// <exception cref="FlickrException">Thrown when the photo id cannot be found.</exception>
 
3538
                public bool PhotosSetMeta(string photoId, string title, string description)
 
3539
                {
 
3540
                        Hashtable parameters = new Hashtable();
 
3541
                        parameters.Add("method", "flickr.photos.setMeta");
 
3542
                        parameters.Add("photo_id", photoId);
 
3543
                        parameters.Add("title", title);
 
3544
                        parameters.Add("description", description);
 
3545
 
 
3546
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3547
 
 
3548
                        if( response.Status == ResponseStatus.OK )
 
3549
                        {
 
3550
                                return true;
 
3551
                        }
 
3552
                        else
 
3553
                        {
 
3554
                                throw new FlickrApiException(response.Error);
 
3555
                        }
 
3556
 
 
3557
                }
 
3558
 
 
3559
                /// <summary>
 
3560
                /// Set the permissions on a photo.
 
3561
                /// </summary>
 
3562
                /// <param name="photoId">The id of the photo to update.</param>
 
3563
                /// <param name="isPublic">1 if the photo is public, 0 if it is not.</param>
 
3564
                /// <param name="isFriend">1 if the photo is viewable by friends, 0 if it is not.</param>
 
3565
                /// <param name="isFamily">1 if the photo is viewable by family, 0 if it is not.</param>
 
3566
                /// <param name="permComment">Who can add comments. See <see cref="PermissionComment"/> for more details.</param>
 
3567
                /// <param name="permAddMeta">Who can add metadata (notes and tags). See <see cref="PermissionAddMeta"/> for more details.</param>
 
3568
                public void PhotosSetPerms(string photoId, int isPublic, int isFriend, int isFamily, PermissionComment permComment, PermissionAddMeta permAddMeta)
 
3569
                {
 
3570
                        PhotosSetPerms(photoId, (isPublic==1), (isFriend==1), (isFamily==1), permComment, permAddMeta);
 
3571
                }
 
3572
 
 
3573
                /// <summary>
 
3574
                /// Set the permissions on a photo.
 
3575
                /// </summary>
 
3576
                /// <param name="photoId">The id of the photo to update.</param>
 
3577
                /// <param name="isPublic">True if the photo is public, False if it is not.</param>
 
3578
                /// <param name="isFriend">True if the photo is viewable by friends, False if it is not.</param>
 
3579
                /// <param name="isFamily">True if the photo is viewable by family, False if it is not.</param>
 
3580
                /// <param name="permComment">Who can add comments. See <see cref="PermissionComment"/> for more details.</param>
 
3581
                /// <param name="permAddMeta">Who can add metadata (notes and tags). See <see cref="PermissionAddMeta"/> for more details.</param>
 
3582
                public void PhotosSetPerms(string photoId, bool isPublic, bool isFriend, bool isFamily, PermissionComment permComment, PermissionAddMeta permAddMeta)
 
3583
                {
 
3584
                        Hashtable parameters = new Hashtable();
 
3585
                        parameters.Add("method", "flickr.photos.setPerms");
 
3586
                        parameters.Add("photo_id", photoId);
 
3587
                        parameters.Add("is_public", (isPublic?"1":"0"));
 
3588
                        parameters.Add("is_friend", (isFriend?"1":"0"));
 
3589
                        parameters.Add("is_family", (isFamily?"1":"0"));
 
3590
                        parameters.Add("perm_comment", permComment.ToString("d"));
 
3591
                        parameters.Add("perm_addmeta", permAddMeta.ToString("d"));
 
3592
 
 
3593
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3594
 
 
3595
                        if( response.Status == ResponseStatus.OK )
 
3596
                        {
 
3597
                                return;
 
3598
                        }
 
3599
                        else
 
3600
                        {
 
3601
                                throw new FlickrApiException(response.Error);
 
3602
                        }
 
3603
 
 
3604
                }
 
3605
 
 
3606
                /// <summary>
 
3607
                /// Set the tags for a photo.
 
3608
                /// </summary>
 
3609
                /// <remarks>
 
3610
                /// This will remove all old tags and add these new ones specified. See <see cref="PhotosAddTags(string, string)"/>
 
3611
                /// to just add new tags without deleting old ones.
 
3612
                /// </remarks>
 
3613
                /// <param name="photoId">The id of the photo to update.</param>
 
3614
                /// <param name="tags">An array of tags.</param>
 
3615
                /// <returns>True if the photo was updated successfully.</returns>
 
3616
                public bool PhotosSetTags(string photoId, string[] tags)
 
3617
                {
 
3618
                        string s = string.Join(",", tags);
 
3619
                        return PhotosSetTags(photoId, s);
 
3620
                }
 
3621
 
 
3622
                /// <summary>
 
3623
                /// Set the tags for a photo.
 
3624
                /// </summary>
 
3625
                /// <remarks>
 
3626
                /// This will remove all old tags and add these new ones specified. See <see cref="PhotosAddTags(string, string)"/>
 
3627
                /// to just add new tags without deleting old ones.
 
3628
                /// </remarks>
 
3629
                /// <param name="photoId">The id of the photo to update.</param>
 
3630
                /// <param name="tags">An comma-seperated list of tags.</param>
 
3631
                /// <returns>True if the photo was updated successfully.</returns>
 
3632
                public bool PhotosSetTags(string photoId, string tags)
 
3633
                {
 
3634
                        Hashtable parameters = new Hashtable();
 
3635
                        parameters.Add("method", "flickr.photos.setTags");
 
3636
                        parameters.Add("photo_id", photoId);
 
3637
                        parameters.Add("tags", tags);
 
3638
 
 
3639
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3640
 
 
3641
                        if( response.Status == ResponseStatus.OK )
 
3642
                        {
 
3643
                                return true;
 
3644
                        }
 
3645
                        else
 
3646
                        {
 
3647
                                throw new FlickrApiException(response.Error);
 
3648
                        }
 
3649
 
 
3650
                }
 
3651
 
 
3652
                /// <summary>
 
3653
                /// Sets the content type for a photo.
 
3654
                /// </summary>
 
3655
                /// <param name="photoId">The ID of the photos to set.</param>
 
3656
                /// <param name="contentType">The new content type.</param>
 
3657
                public void PhotosSetContentType(string photoId, ContentType contentType)
 
3658
                {
 
3659
                        CheckRequiresAuthentication();
 
3660
 
 
3661
                        Hashtable parameters = new Hashtable();
 
3662
                        parameters.Add("method", "flickr.photos.setContentType");
 
3663
                        parameters.Add("photo_id", photoId);
 
3664
                        parameters.Add("content_type", (int)contentType);
 
3665
 
 
3666
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3667
 
 
3668
                        if( response.Status == ResponseStatus.OK )
 
3669
                        {
 
3670
                                return;
 
3671
                        }
 
3672
                        else
 
3673
                        {
 
3674
                                throw new FlickrApiException(response.Error);
 
3675
                        }
 
3676
                }
 
3677
 
 
3678
                /// <summary>
 
3679
                /// Set the safety level for a photo, but only set the hidden aspect.
 
3680
                /// </summary>
 
3681
                /// <param name="photoId">The ID of the photo to set the hidden property for.</param>
 
3682
                /// <param name="hidden">The new value of the hidden value.</param>
 
3683
                public void PhotosSetSafetyLevel(string photoId, HiddenFromSearch hidden)
 
3684
                {
 
3685
                        PhotosSetSafetyLevel(photoId, SafetyLevel.None, hidden);
 
3686
                }
 
3687
 
 
3688
                /// <summary>
 
3689
                /// Set the safety level for a photo.
 
3690
                /// </summary>
 
3691
                /// <param name="photoId">The ID of the photo to set the safety level property for.</param>
 
3692
                /// <param name="safetyLevel">The new value of the safety level value.</param>
 
3693
                public void PhotosSetSafetyLevel(string photoId, SafetyLevel safetyLevel)
 
3694
                {
 
3695
                        PhotosSetSafetyLevel(photoId, safetyLevel, HiddenFromSearch.None);
 
3696
                }
 
3697
 
 
3698
                /// <summary>
 
3699
                /// Sets the safety level and hidden property of a photo.
 
3700
                /// </summary>
 
3701
                /// <param name="photoId">The ID of the photos to set.</param>
 
3702
                /// <param name="safetyLevel">The new content type.</param>
 
3703
                /// <param name="hidden">The new hidden value.</param>
 
3704
                public void PhotosSetSafetyLevel(string photoId, SafetyLevel safetyLevel, HiddenFromSearch hidden)
 
3705
                {
 
3706
                        CheckRequiresAuthentication();
 
3707
 
 
3708
                        Hashtable parameters = new Hashtable();
 
3709
                        parameters.Add("method", "flickr.photos.setSafetyLevel");
 
3710
                        parameters.Add("photo_id", photoId);
 
3711
                        if( safetyLevel != SafetyLevel.None ) parameters.Add("safety_level", (int)safetyLevel);
 
3712
                        switch(hidden)
 
3713
                        {
 
3714
                                case HiddenFromSearch.Visible:
 
3715
                                        parameters.Add("hidden", 0);
 
3716
                                        break;
 
3717
                                case HiddenFromSearch.Hidden:
 
3718
                                        parameters.Add("hidden", 1);
 
3719
                                        break;
 
3720
                        }
 
3721
 
 
3722
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3723
 
 
3724
                        if( response.Status == ResponseStatus.OK )
 
3725
                        {
 
3726
                                return;
 
3727
                        }
 
3728
                        else
 
3729
                        {
 
3730
                                throw new FlickrApiException(response.Error);
 
3731
                        }
 
3732
                }
 
3733
                #endregion
 
3734
 
 
3735
                #region [ Photos Comments ]
 
3736
                /// <summary>
 
3737
                /// Gets a list of comments for a photo.
 
3738
                /// </summary>
 
3739
                /// <param name="photoId">The id of the photo to return the comments for.</param>
 
3740
                /// <returns>An array of <see cref="Comment"/> objects.</returns>
 
3741
                public Comment[] PhotosCommentsGetList(string photoId)
 
3742
                {
 
3743
                        Hashtable parameters = new Hashtable();
 
3744
                        parameters.Add("method", "flickr.photos.comments.getList");
 
3745
                        parameters.Add("photo_id", photoId);
 
3746
 
 
3747
                        FlickrNet.Response response = GetResponseCache(parameters);
 
3748
 
 
3749
                        if( response.Status == ResponseStatus.OK )
 
3750
                        {
 
3751
                                return PhotoComments.GetComments(response.AllElements[0]);
 
3752
                        }
 
3753
                        else
 
3754
                        {
 
3755
                                throw new FlickrApiException(response.Error);
 
3756
                        }
 
3757
                }
 
3758
 
 
3759
                /// <summary>
 
3760
                /// Adds a new comment to a photo.
 
3761
                /// </summary>
 
3762
                /// <param name="photoId">The ID of the photo to add the comment to.</param>
 
3763
                /// <param name="commentText">The text of the comment. Can contain some HTML.</param>
 
3764
                /// <returns>The new ID of the created comment.</returns>
 
3765
                public string PhotosCommentsAddComment(string photoId, string commentText)
 
3766
                {
 
3767
                        Hashtable parameters = new Hashtable();
 
3768
                        parameters.Add("method", "flickr.photos.comments.addComment");
 
3769
                        parameters.Add("photo_id", photoId);
 
3770
                        parameters.Add("comment_text", commentText);
 
3771
 
 
3772
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3773
 
 
3774
                        if( response.Status == ResponseStatus.OK )
 
3775
                        {
 
3776
                                XmlNode node = response.AllElements[0];
 
3777
                                if( node.Attributes.GetNamedItem("id") != null )
 
3778
                                        return node.Attributes.GetNamedItem("id").Value;
 
3779
                                else
 
3780
                                        throw new ResponseXmlException("Comment ID not found in response Xml.");
 
3781
                        }
 
3782
                        else
 
3783
                        {
 
3784
                                throw new FlickrApiException(response.Error);
 
3785
                        }
 
3786
                }
 
3787
 
 
3788
                /// <summary>
 
3789
                /// Deletes a comment from a photo.
 
3790
                /// </summary>
 
3791
                /// <param name="commentId">The ID of the comment to delete.</param>
 
3792
                public void PhotosCommentsDeleteComment(string commentId)
 
3793
                {
 
3794
                        Hashtable parameters = new Hashtable();
 
3795
                        parameters.Add("method", "flickr.photos.comments.deleteComment");
 
3796
                        parameters.Add("comment_id", commentId);
 
3797
 
 
3798
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3799
 
 
3800
                        if( response.Status == ResponseStatus.OK )
 
3801
                        {
 
3802
                                return;
 
3803
                        }
 
3804
                        else
 
3805
                        {
 
3806
                                throw new FlickrApiException(response.Error);
 
3807
                        }
 
3808
                }
 
3809
 
 
3810
                /// <summary>
 
3811
                /// Edits a comment.
 
3812
                /// </summary>
 
3813
                /// <param name="commentId">The ID of the comment to edit.</param>
 
3814
                /// <param name="commentText">The new text for the comment.</param>
 
3815
                public void PhotosCommentsEditComment(string commentId, string commentText)
 
3816
                {
 
3817
                        Hashtable parameters = new Hashtable();
 
3818
                        parameters.Add("method", "flickr.photos.comments.editComment");
 
3819
                        parameters.Add("comment_id", commentId);
 
3820
                        parameters.Add("comment_text", commentText);
 
3821
 
 
3822
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3823
 
 
3824
                        if( response.Status == ResponseStatus.OK )
 
3825
                        {
 
3826
                                return;
 
3827
                        }
 
3828
                        else
 
3829
                        {
 
3830
                                throw new FlickrApiException(response.Error);
 
3831
                        }
 
3832
                }
 
3833
                #endregion
 
3834
 
 
3835
                #region [ Photosets ]
 
3836
                /// <summary>
 
3837
                /// Add a photo to a photoset.
 
3838
                /// </summary>
 
3839
                /// <param name="photosetId">The ID of the photoset to add the photo to.</param>
 
3840
                /// <param name="photoId">The ID of the photo to add.</param>
 
3841
                public void PhotosetsAddPhoto(string photosetId, string photoId)
 
3842
                {
 
3843
                        Hashtable parameters = new Hashtable();
 
3844
                        parameters.Add("method", "flickr.photosets.addPhoto");
 
3845
                        parameters.Add("photoset_id", photosetId);
 
3846
                        parameters.Add("photo_id", photoId);
 
3847
 
 
3848
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3849
 
 
3850
                        if( response.Status == ResponseStatus.OK )
 
3851
                        {
 
3852
                                return;
 
3853
                        }
 
3854
                        else
 
3855
                        {
 
3856
                                throw new FlickrApiException(response.Error);
 
3857
                        }
 
3858
                }
 
3859
 
 
3860
                /// <summary>
 
3861
                /// Creates a blank photoset, with a title and a primary photo (minimum requirements).
 
3862
                /// </summary>
 
3863
                /// <param name="title">The title of the photoset.</param>
 
3864
                /// <param name="primaryPhotoId">The ID of the photo which will be the primary photo for the photoset. This photo will also be added to the set.</param>
 
3865
                /// <returns>The <see cref="Photoset"/> that is created.</returns>
 
3866
                public Photoset PhotosetsCreate(string title, string primaryPhotoId)
 
3867
                {
 
3868
                        return PhotosetsCreate(title, null, primaryPhotoId);
 
3869
                }
 
3870
 
 
3871
                /// <summary>
 
3872
                /// Creates a blank photoset, with a title, description and a primary photo.
 
3873
                /// </summary>
 
3874
                /// <param name="title">The title of the photoset.</param>
 
3875
                /// <param name="description">THe description of the photoset.</param>
 
3876
                /// <param name="primaryPhotoId">The ID of the photo which will be the primary photo for the photoset. This photo will also be added to the set.</param>
 
3877
                /// <returns>The <see cref="Photoset"/> that is created.</returns>
 
3878
                public Photoset PhotosetsCreate(string title, string description, string primaryPhotoId)
 
3879
                {
 
3880
                        Hashtable parameters = new Hashtable();
 
3881
                        parameters.Add("method", "flickr.photosets.create");
 
3882
                        parameters.Add("title", title);
 
3883
                        parameters.Add("primary_photo_id", primaryPhotoId);
 
3884
                        parameters.Add("description", description);
 
3885
 
 
3886
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3887
 
 
3888
                        if( response.Status == ResponseStatus.OK )
 
3889
                        {
 
3890
                                return response.Photoset;
 
3891
                        }
 
3892
                        else
 
3893
                        {
 
3894
                                throw new FlickrApiException(response.Error);
 
3895
                        }
 
3896
 
 
3897
                }
 
3898
 
 
3899
                /// <summary>
 
3900
                /// Deletes the specified photoset.
 
3901
                /// </summary>
 
3902
                /// <param name="photosetId">The ID of the photoset to delete.</param>
 
3903
                /// <returns>Returns true when the photoset has been deleted.</returns>
 
3904
                public bool PhotosetsDelete(string photosetId)
 
3905
                {
 
3906
                        Hashtable parameters = new Hashtable();
 
3907
                        parameters.Add("method", "flickr.photosets.delete");
 
3908
                        parameters.Add("photoset_id", photosetId);
 
3909
 
 
3910
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3911
 
 
3912
                        if( response.Status == ResponseStatus.OK )
 
3913
                        {
 
3914
                                return true;
 
3915
                        }
 
3916
                        else
 
3917
                        {
 
3918
                                throw new FlickrApiException(response.Error);
 
3919
                        }
 
3920
 
 
3921
                }
 
3922
 
 
3923
                /// <summary>
 
3924
                /// Updates the title and description for a photoset.
 
3925
                /// </summary>
 
3926
                /// <param name="photosetId">The ID of the photoset to update.</param>
 
3927
                /// <param name="title">The new title for the photoset.</param>
 
3928
                /// <param name="description">The new description for the photoset.</param>
 
3929
                /// <returns>Returns true when the photoset has been updated.</returns>
 
3930
                public bool PhotosetsEditMeta(string photosetId, string title, string description)
 
3931
                {
 
3932
                        Hashtable parameters = new Hashtable();
 
3933
                        parameters.Add("method", "flickr.photosets.editMeta");
 
3934
                        parameters.Add("photoset_id", photosetId);
 
3935
                        parameters.Add("title", title);
 
3936
                        parameters.Add("description", description);
 
3937
 
 
3938
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3939
 
 
3940
                        if( response.Status == ResponseStatus.OK )
 
3941
                        {
 
3942
                                return true;
 
3943
                        }
 
3944
                        else
 
3945
                        {
 
3946
                                throw new FlickrApiException(response.Error);
 
3947
                        }
 
3948
 
 
3949
                }
 
3950
 
 
3951
                /// <summary>
 
3952
                /// Sets the photos for a photoset.
 
3953
                /// </summary>
 
3954
                /// <remarks>
 
3955
                /// Will remove any previous photos from the photoset.
 
3956
                /// The order in thich the photoids are given is the order they will appear in the
 
3957
                /// photoset page.
 
3958
                /// </remarks>
 
3959
                /// <param name="photosetId">The ID of the photoset to update.</param>
 
3960
                /// <param name="primaryPhotoId">The ID of the new primary photo for the photoset.</param>
 
3961
                /// <param name="photoIds">An array of photo IDs.</param>
 
3962
                /// <returns>Returns true when the photoset has been updated.</returns>
 
3963
                public bool PhotosetsEditPhotos(string photosetId, string primaryPhotoId, string[] photoIds)
 
3964
                {
 
3965
                        return PhotosetsEditPhotos(photosetId, primaryPhotoId, string.Join(",", photoIds));
 
3966
                }
 
3967
 
 
3968
 
 
3969
                /// <summary>
 
3970
                /// Sets the photos for a photoset.
 
3971
                /// </summary>
 
3972
                /// <remarks>
 
3973
                /// Will remove any previous photos from the photoset.
 
3974
                /// The order in thich the photoids are given is the order they will appear in the
 
3975
                /// photoset page.
 
3976
                /// </remarks>
 
3977
                /// <param name="photosetId">The ID of the photoset to update.</param>
 
3978
                /// <param name="primaryPhotoId">The ID of the new primary photo for the photoset.</param>
 
3979
                /// <param name="photoIds">An comma seperated list of photo IDs.</param>
 
3980
                /// <returns>Returns true when the photoset has been updated.</returns>
 
3981
                public bool PhotosetsEditPhotos(string photosetId, string primaryPhotoId, string photoIds)
 
3982
                {
 
3983
                        Hashtable parameters = new Hashtable();
 
3984
                        parameters.Add("method", "flickr.photosets.editPhotos");
 
3985
                        parameters.Add("photoset_id", photosetId);
 
3986
                        parameters.Add("primary_photo_id", primaryPhotoId);
 
3987
                        parameters.Add("photo_ids", photoIds);
 
3988
 
 
3989
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
3990
 
 
3991
                        if( response.Status == ResponseStatus.OK )
 
3992
                        {
 
3993
                                return true;
 
3994
                        }
 
3995
                        else
 
3996
                        {
 
3997
                                throw new FlickrApiException(response.Error);
 
3998
                        }
 
3999
 
 
4000
                }
 
4001
 
 
4002
                /// <summary>
 
4003
                /// Gets the context of the specified photo within the photoset.
 
4004
                /// </summary>
 
4005
                /// <param name="photoId">The photo id of the photo in the set.</param>
 
4006
                /// <param name="photosetId">The id of the set.</param>
 
4007
                /// <returns><see cref="Context"/> of the specified photo.</returns>
 
4008
                public Context PhotosetsGetContext(string photoId, string photosetId)
 
4009
                {
 
4010
                        Hashtable parameters = new Hashtable();
 
4011
                        parameters.Add("method", "flickr.photosets.getContext");
 
4012
                        parameters.Add("photo_id", photoId);
 
4013
                        parameters.Add("photoset_id", photosetId);
 
4014
 
 
4015
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4016
 
 
4017
                        if( response.Status == ResponseStatus.OK )
 
4018
                        {
 
4019
                                Context c = new Context();
 
4020
                                c.Count = response.ContextCount.Count;
 
4021
                                c.NextPhoto = response.ContextNextPhoto;
 
4022
                                c.PreviousPhoto = response.ContextPrevPhoto;
 
4023
 
 
4024
                                return c;
 
4025
                        }
 
4026
                        else
 
4027
                        {
 
4028
                                throw new FlickrApiException(response.Error);
 
4029
                        }
 
4030
                }
 
4031
 
 
4032
                /// <summary>
 
4033
                /// Gets the information about a photoset.
 
4034
                /// </summary>
 
4035
                /// <param name="photosetId">The ID of the photoset to return information for.</param>
 
4036
                /// <returns>A <see cref="Photoset"/> instance.</returns>
 
4037
                public Photoset PhotosetsGetInfo(string photosetId)
 
4038
                {
 
4039
                        Hashtable parameters = new Hashtable();
 
4040
                        parameters.Add("method", "flickr.photosets.getInfo");
 
4041
                        parameters.Add("photoset_id", photosetId);
 
4042
 
 
4043
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4044
 
 
4045
                        if( response.Status == ResponseStatus.OK )
 
4046
                        {
 
4047
                                return response.Photoset;
 
4048
                        }
 
4049
                        else
 
4050
                        {
 
4051
                                throw new FlickrApiException(response.Error);
 
4052
                        }
 
4053
 
 
4054
                }
 
4055
 
 
4056
                /// <summary>
 
4057
                /// Gets a list of the currently authenticated users photosets.
 
4058
                /// </summary>
 
4059
                /// <returns>A <see cref="Photosets"/> instance containing a collection of photosets.</returns>
 
4060
                public Photosets PhotosetsGetList()
 
4061
                {
 
4062
                        return PhotosetsGetList(null);
 
4063
                }
 
4064
 
 
4065
                /// <summary>
 
4066
                /// Gets a list of the specified users photosets.
 
4067
                /// </summary>
 
4068
                /// <param name="userId">The ID of the user to return the photosets of.</param>
 
4069
                /// <returns>A <see cref="Photosets"/> instance containing a collection of photosets.</returns>
 
4070
                public Photosets PhotosetsGetList(string userId)
 
4071
                {
 
4072
                        Hashtable parameters = new Hashtable();
 
4073
                        parameters.Add("method", "flickr.photosets.getList");
 
4074
                        if( userId != null ) parameters.Add("user_id", userId);
 
4075
 
 
4076
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4077
 
 
4078
                        if( response.Status == ResponseStatus.OK )
 
4079
                        {
 
4080
                                return response.Photosets;
 
4081
                        }
 
4082
                        else
 
4083
                        {
 
4084
                                throw new FlickrApiException(response.Error);
 
4085
                        }
 
4086
                }
 
4087
 
 
4088
                /// <summary>
 
4089
                /// Gets a collection of photos for a photoset.
 
4090
                /// </summary>
 
4091
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4092
                /// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
 
4093
                public Photoset PhotosetsGetPhotos(string photosetId)
 
4094
                {
 
4095
                        return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, PrivacyFilter.None, 0, 0);
 
4096
                }
 
4097
 
 
4098
                /// <summary>
 
4099
                /// Gets a collection of photos for a photoset.
 
4100
                /// </summary>
 
4101
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4102
                /// <param name="page">The page to return, defaults to 1.</param>
 
4103
                /// <param name="perPage">The number of photos to return per page.</param>
 
4104
                /// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
 
4105
                public Photoset PhotosetsGetPhotos(string photosetId, int page, int perPage)
 
4106
                {
 
4107
                        return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, PrivacyFilter.None, page, perPage);
 
4108
                }
 
4109
 
 
4110
                /// <summary>
 
4111
                /// Gets a collection of photos for a photoset.
 
4112
                /// </summary>
 
4113
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4114
                /// <param name="privacyFilter">The privacy filter to search on.</param>
 
4115
                /// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
 
4116
                public Photoset PhotosetsGetPhotos(string photosetId, PrivacyFilter privacyFilter)
 
4117
                {
 
4118
                        return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, privacyFilter, 0, 0);
 
4119
                }
 
4120
 
 
4121
                /// <summary>
 
4122
                /// Gets a collection of photos for a photoset.
 
4123
                /// </summary>
 
4124
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4125
                /// <param name="privacyFilter">The privacy filter to search on.</param>
 
4126
                /// <param name="page">The page to return, defaults to 1.</param>
 
4127
                /// <param name="perPage">The number of photos to return per page.</param>
 
4128
                /// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
 
4129
                public Photoset PhotosetsGetPhotos(string photosetId, PrivacyFilter privacyFilter, int page, int perPage)
 
4130
                {
 
4131
                        return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, privacyFilter, page, perPage);
 
4132
                }
 
4133
 
 
4134
                /// <summary>
 
4135
                /// Gets a collection of photos for a photoset.
 
4136
                /// </summary>
 
4137
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4138
                /// <param name="extras">The extras to return for each photo.</param>
 
4139
                /// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
 
4140
                public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras)
 
4141
                {
 
4142
                        return PhotosetsGetPhotos(photosetId, extras, PrivacyFilter.None, 0, 0);
 
4143
                }
 
4144
 
 
4145
                /// <summary>
 
4146
                /// Gets a collection of photos for a photoset.
 
4147
                /// </summary>
 
4148
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4149
                /// <param name="extras">The extras to return for each photo.</param>
 
4150
                /// <param name="page">The page to return, defaults to 1.</param>
 
4151
                /// <param name="perPage">The number of photos to return per page.</param>
 
4152
                /// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
 
4153
                public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras, int page, int perPage)
 
4154
                {
 
4155
                        return PhotosetsGetPhotos(photosetId, extras, PrivacyFilter.None, page, perPage);
 
4156
                }
 
4157
 
 
4158
                /// <summary>
 
4159
                /// Gets a collection of photos for a photoset.
 
4160
                /// </summary>
 
4161
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4162
                /// <param name="extras">The extras to return for each photo.</param>
 
4163
                /// <param name="privacyFilter">The privacy filter to search on.</param>
 
4164
                /// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
 
4165
                public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras, PrivacyFilter privacyFilter)
 
4166
                {
 
4167
                        return PhotosetsGetPhotos(photosetId, extras, privacyFilter, 0, 0);
 
4168
                }
 
4169
 
 
4170
                /// <summary>
 
4171
                /// Gets a collection of photos for a photoset.
 
4172
                /// </summary>
 
4173
                /// <param name="photosetId">The ID of the photoset to return photos for.</param>
 
4174
                /// <param name="extras">The extras to return for each photo.</param>
 
4175
                /// <param name="privacyFilter">The privacy filter to search on.</param>
 
4176
                /// <param name="page">The page to return, defaults to 1.</param>
 
4177
                /// <param name="perPage">The number of photos to return per page.</param>
 
4178
                /// <returns>An array of <see cref="Photo"/> instances.</returns>
 
4179
                public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras, PrivacyFilter privacyFilter, int page, int perPage)
 
4180
                {
 
4181
                        Hashtable parameters = new Hashtable();
 
4182
                        parameters.Add("method", "flickr.photosets.getPhotos");
 
4183
                        parameters.Add("photoset_id", photosetId);
 
4184
                        if( extras != PhotoSearchExtras.None ) parameters.Add("extras", Utils.ExtrasToString(extras));
 
4185
                        if( privacyFilter != PrivacyFilter.None ) parameters.Add("privacy_filter", privacyFilter.ToString("d"));
 
4186
                        if( page > 0 ) parameters.Add("page", page);
 
4187
                        if( perPage > 0 ) parameters.Add("per_page", perPage);
 
4188
 
 
4189
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4190
 
 
4191
                        if( response.Status == ResponseStatus.OK )
 
4192
                        {
 
4193
                                if( response.Photoset.OwnerId != null && response.Photoset.OwnerId.Length > 0 )
 
4194
                                {
 
4195
                                        foreach(Photo p in response.Photoset.PhotoCollection)
 
4196
                                        {
 
4197
                                                p.UserId = response.Photoset.OwnerId;
 
4198
                                        }
 
4199
                                }
 
4200
                                return response.Photoset;
 
4201
                        }
 
4202
                        else
 
4203
                        {
 
4204
                                throw new FlickrApiException(response.Error);
 
4205
                        }
 
4206
                }
 
4207
 
 
4208
                /// <summary>
 
4209
                /// Changes the order of your photosets.
 
4210
                /// </summary>
 
4211
                /// <param name="photosetIds">An array of photoset IDs,
 
4212
                /// ordered with the set to show first, first in the list.
 
4213
                /// Any set IDs not given in the list will be set to appear at the end of the list, ordered by their IDs.</param>
 
4214
                public void PhotosetsOrderSets(string[] photosetIds)
 
4215
                {
 
4216
                        PhotosetsOrderSets(string.Join(",", photosetIds));
 
4217
                }
 
4218
 
 
4219
                /// <summary>
 
4220
                /// Changes the order of your photosets.
 
4221
                /// </summary>
 
4222
                /// <param name="photosetIds">A comma delimited list of photoset IDs,
 
4223
                /// ordered with the set to show first, first in the list.
 
4224
                /// Any set IDs not given in the list will be set to appear at the end of the list, ordered by their IDs.</param>
 
4225
                public void PhotosetsOrderSets(string photosetIds)
 
4226
                {
 
4227
                        Hashtable parameters = new Hashtable();
 
4228
                        parameters.Add("method", "flickr.photosets.orderSets");
 
4229
                        parameters.Add("photosetIds", photosetIds);
 
4230
 
 
4231
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4232
 
 
4233
                        if( response.Status == ResponseStatus.OK )
 
4234
                        {
 
4235
                                return;
 
4236
                        }
 
4237
                        else
 
4238
                        {
 
4239
                                throw new FlickrApiException(response.Error);
 
4240
                        }
 
4241
                }
 
4242
 
 
4243
                /// <summary>
 
4244
                /// Removes a photo from a photoset.
 
4245
                /// </summary>
 
4246
                /// <remarks>
 
4247
                /// An exception will be raised if the photo is not in the set.
 
4248
                /// </remarks>
 
4249
                /// <param name="photosetId">The ID of the photoset to remove the photo from.</param>
 
4250
                /// <param name="photoId">The ID of the photo to remove.</param>
 
4251
                public void PhotosetsRemovePhoto(string photosetId, string photoId)
 
4252
                {
 
4253
                        Hashtable parameters = new Hashtable();
 
4254
                        parameters.Add("method", "flickr.photosets.removePhoto");
 
4255
                        parameters.Add("photoset_id", photosetId);
 
4256
                        parameters.Add("photo_id", photoId);
 
4257
 
 
4258
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4259
 
 
4260
                        if( response.Status == ResponseStatus.OK )
 
4261
                        {
 
4262
                                return;
 
4263
                        }
 
4264
                        else
 
4265
                        {
 
4266
                                throw new FlickrApiException(response.Error);
 
4267
                        }
 
4268
                }
 
4269
                #endregion
 
4270
 
 
4271
                #region [ Photoset Comments ]
 
4272
                /// <summary>
 
4273
                /// Gets a list of comments for a photoset.
 
4274
                /// </summary>
 
4275
                /// <param name="photosetId">The id of the photoset to return the comments for.</param>
 
4276
                /// <returns>An array of <see cref="Comment"/> objects.</returns>
 
4277
                public Comment[] PhotosetsCommentsGetList(string photosetId)
 
4278
                {
 
4279
                        Hashtable parameters = new Hashtable();
 
4280
                        parameters.Add("method", "flickr.photosets.comments.getList");
 
4281
                        parameters.Add("photoset_id", photosetId);
 
4282
 
 
4283
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4284
 
 
4285
                        if( response.Status == ResponseStatus.OK )
 
4286
                        {
 
4287
                                return PhotoComments.GetComments(response.AllElements[0]);
 
4288
                        }
 
4289
                        else
 
4290
                        {
 
4291
                                throw new FlickrApiException(response.Error);
 
4292
                        }
 
4293
                }
 
4294
 
 
4295
                /// <summary>
 
4296
                /// Adds a new comment to a photoset.
 
4297
                /// </summary>
 
4298
                /// <param name="photosetId">The ID of the photoset to add the comment to.</param>
 
4299
                /// <param name="commentText">The text of the comment. Can contain some HTML.</param>
 
4300
                /// <returns>The new ID of the created comment.</returns>
 
4301
                public string PhotosetsCommentsAddComment(string photosetId, string commentText)
 
4302
                {
 
4303
                        Hashtable parameters = new Hashtable();
 
4304
                        parameters.Add("method", "flickr.photosets.comments.addComment");
 
4305
                        parameters.Add("photoset_id", photosetId);
 
4306
                        parameters.Add("comment_text", commentText);
 
4307
 
 
4308
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4309
 
 
4310
                        if( response.Status == ResponseStatus.OK )
 
4311
                        {
 
4312
                                XmlNode node = response.AllElements[0];
 
4313
                                if( node.Attributes.GetNamedItem("id") != null )
 
4314
                                        return node.Attributes.GetNamedItem("id").Value;
 
4315
                                else
 
4316
                                        throw new ResponseXmlException("Comment ID not found in response.");
 
4317
                        }
 
4318
                        else
 
4319
                        {
 
4320
                                throw new FlickrApiException(response.Error);
 
4321
                        }
 
4322
                }
 
4323
 
 
4324
                /// <summary>
 
4325
                /// Deletes a comment from a photoset.
 
4326
                /// </summary>
 
4327
                /// <param name="commentId">The ID of the comment to delete.</param>
 
4328
                public void PhotosetsCommentsDeleteComment(string commentId)
 
4329
                {
 
4330
                        Hashtable parameters = new Hashtable();
 
4331
                        parameters.Add("method", "flickr.photosets.comments.deleteComment");
 
4332
                        parameters.Add("comment_id", commentId);
 
4333
 
 
4334
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4335
 
 
4336
                        if( response.Status == ResponseStatus.OK )
 
4337
                        {
 
4338
                                return;
 
4339
                        }
 
4340
                        else
 
4341
                        {
 
4342
                                throw new FlickrApiException(response.Error);
 
4343
                        }
 
4344
                }
 
4345
 
 
4346
                /// <summary>
 
4347
                /// Edits a comment.
 
4348
                /// </summary>
 
4349
                /// <param name="commentId">The ID of the comment to edit.</param>
 
4350
                /// <param name="commentText">The new text for the comment.</param>
 
4351
                public void PhotosetsCommentsEditComment(string commentId, string commentText)
 
4352
                {
 
4353
                        Hashtable parameters = new Hashtable();
 
4354
                        parameters.Add("method", "flickr.photosets.comments.editComment");
 
4355
                        parameters.Add("comment_id", commentId);
 
4356
                        parameters.Add("comment_text", commentText);
 
4357
 
 
4358
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4359
 
 
4360
                        if( response.Status == ResponseStatus.OK )
 
4361
                        {
 
4362
                                return;
 
4363
                        }
 
4364
                        else
 
4365
                        {
 
4366
                                throw new FlickrApiException(response.Error);
 
4367
                        }
 
4368
                }
 
4369
                #endregion
 
4370
 
 
4371
                #region [ Prefs ]
 
4372
                /// <summary>
 
4373
                /// Gets the currently authenticated users default safety level.
 
4374
                /// </summary>
 
4375
                /// <returns></returns>
 
4376
                public SafetyLevel PrefsGetSafetyLevel()
 
4377
                {
 
4378
                        CheckRequiresAuthentication();
 
4379
 
 
4380
                        Hashtable parameters = new Hashtable();
 
4381
                        parameters.Add("method", "flickr.prefs.getSafetyLevel");
 
4382
 
 
4383
                        Response res = GetResponseCache(parameters);
 
4384
                        if( res.Status == ResponseStatus.OK )
 
4385
                        {
 
4386
                                string s = res.AllElements[0].GetAttribute("safety_level");
 
4387
                                return (SafetyLevel)int.Parse(s);
 
4388
                        }
 
4389
                        else
 
4390
                        {
 
4391
                                throw new FlickrApiException(res.Error);
 
4392
                        }
 
4393
                }
 
4394
 
 
4395
                /// <summary>
 
4396
                /// Gets the currently authenticated users default hidden from search setting.
 
4397
                /// </summary>
 
4398
                /// <returns></returns>
 
4399
                public HiddenFromSearch PrefsGetHidden()
 
4400
                {
 
4401
                        CheckRequiresAuthentication();
 
4402
 
 
4403
                        Hashtable parameters = new Hashtable();
 
4404
                        parameters.Add("method", "flickr.prefs.getHidden");
 
4405
 
 
4406
                        Response res = GetResponseCache(parameters);
 
4407
                        if( res.Status == ResponseStatus.OK )
 
4408
                        {
 
4409
                                string s = res.AllElements[0].GetAttribute("hidden");
 
4410
                                return (HiddenFromSearch)int.Parse(s);
 
4411
                        }
 
4412
                        else
 
4413
                        {
 
4414
                                throw new FlickrApiException(res.Error);
 
4415
                        }
 
4416
                }
 
4417
 
 
4418
                /// <summary>
 
4419
                /// Gets the currently authenticated users default content type.
 
4420
                /// </summary>
 
4421
                /// <returns></returns>
 
4422
                public ContentType PrefsGetContentType()
 
4423
                {
 
4424
                        CheckRequiresAuthentication();
 
4425
 
 
4426
                        Hashtable parameters = new Hashtable();
 
4427
                        parameters.Add("method", "flickr.prefs.getContentType");
 
4428
 
 
4429
                        Response res = GetResponseCache(parameters);
 
4430
                        if( res.Status == ResponseStatus.OK )
 
4431
                        {
 
4432
                                string s = res.AllElements[0].GetAttribute("content_type");
 
4433
                                return (ContentType)int.Parse(s);
 
4434
                        }
 
4435
                        else
 
4436
                        {
 
4437
                                throw new FlickrApiException(res.Error);
 
4438
                        }
 
4439
                }
 
4440
                #endregion
 
4441
 
 
4442
                #region [ Tags ]
 
4443
                /// <summary>
 
4444
                /// Get the tag list for a given photo.
 
4445
                /// </summary>
 
4446
                /// <param name="photoId">The id of the photo to return tags for.</param>
 
4447
                /// <returns>An instance of the <see cref="PhotoInfo"/> class containing only the <see cref="PhotoInfo.Tags"/> property.</returns>
 
4448
                public PhotoInfoTag[] TagsGetListPhoto(string photoId)
 
4449
                {
 
4450
                        Hashtable parameters = new Hashtable();
 
4451
                        parameters.Add("method", "flickr.tags.getListPhoto");
 
4452
                        parameters.Add("api_key", _apiKey);
 
4453
                        parameters.Add("photo_id", photoId);
 
4454
 
 
4455
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4456
 
 
4457
                        if( response.Status == ResponseStatus.OK )
 
4458
                        {
 
4459
                                return response.PhotoInfo.Tags.TagCollection;
 
4460
                        }
 
4461
                        else
 
4462
                        {
 
4463
                                throw new FlickrApiException(response.Error);
 
4464
                        }
 
4465
                }
 
4466
 
 
4467
                /// <summary>
 
4468
                /// Get the tag list for a given user (or the currently logged in user).
 
4469
                /// </summary>
 
4470
                /// <returns>An array of <see cref="Tag"/> objects.</returns>
 
4471
                public Tag[] TagsGetListUser()
 
4472
                {
 
4473
                        return TagsGetListUser(null);
 
4474
                }
 
4475
 
 
4476
                /// <summary>
 
4477
                /// Get the tag list for a given user (or the currently logged in user).
 
4478
                /// </summary>
 
4479
                /// <param name="userId">The NSID of the user to fetch the tag list for. If this argument is not specified, the currently logged in user (if any) is assumed.</param>
 
4480
                /// <returns>An array of <see cref="Tag"/> objects.</returns>
 
4481
                public Tag[] TagsGetListUser(string userId)
 
4482
                {
 
4483
                        Hashtable parameters = new Hashtable();
 
4484
                        parameters.Add("method", "flickr.tags.getListUser");
 
4485
                        if( userId != null && userId.Length > 0 ) parameters.Add("user_id", userId);
 
4486
 
 
4487
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4488
 
 
4489
                        if( response.Status == ResponseStatus.OK )
 
4490
                        {
 
4491
                                XmlNodeList nodes = response.AllElements[0].SelectNodes("//tag");
 
4492
                                Tag[] tags = new Tag[nodes.Count];
 
4493
                                for(int i = 0; i < tags.Length; i++)
 
4494
                                {
 
4495
                                        tags[i] = new Tag(nodes[i]);
 
4496
                                }
 
4497
                                return tags;
 
4498
                        }
 
4499
                        else
 
4500
                        {
 
4501
                                throw new FlickrApiException(response.Error);
 
4502
                        }
 
4503
                }
 
4504
 
 
4505
                /// <summary>
 
4506
                /// Get the popular tags for a given user (or the currently logged in user).
 
4507
                /// </summary>
 
4508
                /// <returns>An array of <see cref="Tag"/> objects.</returns>
 
4509
                public Tag[] TagsGetListUserPopular()
 
4510
                {
 
4511
                        return TagsGetListUserPopular(null, 0);
 
4512
                }
 
4513
 
 
4514
                /// <summary>
 
4515
                /// Get the popular tags for a given user (or the currently logged in user).
 
4516
                /// </summary>
 
4517
                /// <param name="count">Number of popular tags to return. defaults to 10 when this argument is not present.</param>
 
4518
                /// <returns>An array of <see cref="Tag"/> objects.</returns>
 
4519
                public Tag[] TagsGetListUserPopular(int count)
 
4520
                {
 
4521
                        return TagsGetListUserPopular(null, count);
 
4522
                }
 
4523
 
 
4524
                /// <summary>
 
4525
                /// Get the popular tags for a given user (or the currently logged in user).
 
4526
                /// </summary>
 
4527
                /// <param name="userId">The NSID of the user to fetch the tag list for. If this argument is not specified, the currently logged in user (if any) is assumed.</param>
 
4528
                /// <returns>An array of <see cref="Tag"/> objects.</returns>
 
4529
                public Tag[] TagsGetListUserPopular(string userId)
 
4530
                {
 
4531
                        return TagsGetListUserPopular(userId, 0);
 
4532
                }
 
4533
 
 
4534
                /// <summary>
 
4535
                /// Get the popular tags for a given user (or the currently logged in user).
 
4536
                /// </summary>
 
4537
                /// <param name="userId">The NSID of the user to fetch the tag list for. If this argument is not specified, the currently logged in user (if any) is assumed.</param>
 
4538
                /// <param name="count">Number of popular tags to return. defaults to 10 when this argument is not present.</param>
 
4539
                /// <returns>An array of <see cref="Tag"/> objects.</returns>
 
4540
                public Tag[] TagsGetListUserPopular(string userId, long count)
 
4541
                {
 
4542
                        Hashtable parameters = new Hashtable();
 
4543
                        parameters.Add("method", "flickr.tags.getListUserPopular");
 
4544
                        if( userId != null ) parameters.Add("user_id", userId);
 
4545
                        if( count > 0 ) parameters.Add("count", count.ToString());
 
4546
 
 
4547
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4548
 
 
4549
                        if( response.Status == ResponseStatus.OK )
 
4550
                        {
 
4551
                                XmlNodeList nodes = response.AllElements[0].SelectNodes("//tag");
 
4552
                                Tag[] tags = new Tag[nodes.Count];
 
4553
                                for(int i = 0; i < tags.Length; i++)
 
4554
                                {
 
4555
                                        tags[i] = new Tag(nodes[i]);
 
4556
                                }
 
4557
                                return tags;
 
4558
                        }
 
4559
                        else
 
4560
                        {
 
4561
                                throw new FlickrApiException(response.Error);
 
4562
                        }
 
4563
                }
 
4564
 
 
4565
                /// <summary>
 
4566
                /// Returns a list of tags 'related' to the given tag, based on clustered usage analysis.
 
4567
                /// </summary>
 
4568
                /// <param name="tag">The tag to fetch related tags for.</param>
 
4569
                /// <returns>An array of <see cref="Tag"/> objects.</returns>
 
4570
                public Tag[] TagsGetRelated(string tag)
 
4571
                {
 
4572
                        Hashtable parameters = new Hashtable();
 
4573
                        parameters.Add("method", "flickr.tags.getRelated");
 
4574
                        parameters.Add("api_key", _apiKey);
 
4575
                        parameters.Add("tag", tag);
 
4576
 
 
4577
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4578
 
 
4579
                        if( response.Status == ResponseStatus.OK )
 
4580
                        {
 
4581
                                XmlNodeList nodes = response.AllElements[0].SelectNodes("//tag");
 
4582
                                Tag[] tags = new Tag[nodes.Count];
 
4583
                                for(int i = 0; i < tags.Length; i++)
 
4584
                                {
 
4585
                                        tags[i] = new Tag(nodes[i]);
 
4586
                                }
 
4587
                                return tags;
 
4588
                        }
 
4589
                        else
 
4590
                        {
 
4591
                                throw new FlickrApiException(response.Error);
 
4592
                        }
 
4593
                }
 
4594
 
 
4595
                #endregion
 
4596
 
 
4597
                #region [ Transform ]
 
4598
 
 
4599
                /// <summary>
 
4600
                /// Rotates a photo on Flickr.
 
4601
                /// </summary>
 
4602
                /// <remarks>
 
4603
                /// Does not rotate the original photo.
 
4604
                /// </remarks>
 
4605
                /// <param name="photoId">The ID of the photo.</param>
 
4606
                /// <param name="degrees">The number of degrees to rotate by. Valid values are 90, 180 and 270.</param>
 
4607
                public void TransformRotate(string photoId, int degrees)
 
4608
                {
 
4609
                        if( photoId == null )
 
4610
                                throw new ArgumentNullException("photoId");
 
4611
                        if( degrees != 90 && degrees != 180 && degrees != 270 )
 
4612
                                throw new ArgumentException("Must be 90, 180 or 270", "degrees");
 
4613
 
 
4614
                        Hashtable parameters = new Hashtable();
 
4615
                        parameters.Add("method", "flickr.photos.transform.rotate");
 
4616
                        parameters.Add("photo_id", photoId);
 
4617
                        parameters.Add("degrees", degrees.ToString("0"));
 
4618
 
 
4619
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4620
                        if( response.Status == ResponseStatus.OK )
 
4621
                        {
 
4622
                                return;
 
4623
                        }
 
4624
                        else
 
4625
                        {
 
4626
                                throw new FlickrApiException(response.Error);
 
4627
                        }
 
4628
                }
 
4629
 
 
4630
                #endregion
 
4631
 
 
4632
                #region [ Geo ]
 
4633
                /// <summary>
 
4634
                /// Returns the location data for a give photo.
 
4635
                /// </summary>
 
4636
                /// <param name="photoId">The ID of the photo to return the location information for.</param>
 
4637
                /// <returns>Returns null if the photo has no location information, otherwise returns the location information.</returns>
 
4638
                public PhotoLocation PhotosGeoGetLocation(string photoId)
 
4639
                {
 
4640
                        Hashtable parameters = new Hashtable();
 
4641
                        parameters.Add("method", "flickr.photos.geo.getLocation");
 
4642
                        parameters.Add("photo_id", photoId);
 
4643
 
 
4644
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4645
                        if( response.Status == ResponseStatus.OK )
 
4646
                        {
 
4647
                                return response.PhotoInfo.Location;
 
4648
                        }
 
4649
                        else
 
4650
                        {
 
4651
                                if( response.Error.Code == 2 )
 
4652
                                        return null;
 
4653
                                else
 
4654
                                        throw new FlickrApiException(response.Error);
 
4655
                        }
 
4656
                }
 
4657
                /// <summary>
 
4658
                /// Sets the geo location for a photo.
 
4659
                /// </summary>
 
4660
                /// <param name="photoId">The ID of the photo to set to location for.</param>
 
4661
                /// <param name="latitude">The latitude of the geo location. A double number ranging from -180.00 to 180.00. Digits beyond 6 decimal places will be truncated.</param>
 
4662
                /// <param name="longitude">The longitude of the geo location. A double number ranging from -180.00 to 180.00. Digits beyond 6 decimal places will be truncated.</param>
 
4663
                public void PhotosGeoSetLocation(string photoId, double latitude, double longitude)
 
4664
                {
 
4665
                        PhotosGeoSetLocation(photoId, latitude, longitude, GeoAccuracy.None);
 
4666
                }
 
4667
 
 
4668
                /// <summary>
 
4669
                /// Sets the geo location for a photo.
 
4670
                /// </summary>
 
4671
                /// <param name="photoId">The ID of the photo to set to location for.</param>
 
4672
                /// <param name="latitude">The latitude of the geo location. A double number ranging from -180.00 to 180.00. Digits beyond 6 decimal places will be truncated.</param>
 
4673
                /// <param name="longitude">The longitude of the geo location. A double number ranging from -180.00 to 180.00. Digits beyond 6 decimal places will be truncated.</param>
 
4674
                /// <param name="accuracy">The accuracy of the photos geo location.</param>
 
4675
                public void PhotosGeoSetLocation(string photoId, double latitude, double longitude, GeoAccuracy accuracy)
 
4676
                {
 
4677
                        System.Globalization.NumberFormatInfo nfi = System.Globalization.NumberFormatInfo.InvariantInfo;
 
4678
                        Hashtable parameters = new Hashtable();
 
4679
                        parameters.Add("method", "flickr.photos.geo.setLocation");
 
4680
                        parameters.Add("photo_id", photoId);
 
4681
                        parameters.Add("lat", latitude.ToString(nfi));
 
4682
                        parameters.Add("lon", longitude.ToString(nfi));
 
4683
                        if( accuracy != GeoAccuracy.None )
 
4684
                                parameters.Add("accuracy", ((int)accuracy).ToString());
 
4685
 
 
4686
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4687
                        if( response.Status == ResponseStatus.OK )
 
4688
                        {
 
4689
                                return;
 
4690
                        }
 
4691
                        else
 
4692
                        {
 
4693
                                throw new FlickrApiException(response.Error);
 
4694
                        }
 
4695
                }
 
4696
 
 
4697
                /// <summary>
 
4698
                /// Removes Location information.
 
4699
                /// </summary>
 
4700
                /// <param name="photoId">The photo ID of the photo to remove information from.</param>
 
4701
                /// <returns>Returns true if the location information as found and removed. Returns false if no photo information was found.</returns>
 
4702
                public bool PhotosGeoRemoveLocation(string photoId)
 
4703
                {
 
4704
                        Hashtable parameters = new Hashtable();
 
4705
                        parameters.Add("method", "flickr.photos.geo.removeLocation");
 
4706
                        parameters.Add("photo_id", photoId);
 
4707
 
 
4708
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4709
                        if( response.Status == ResponseStatus.OK )
 
4710
                        {
 
4711
                                return true;
 
4712
                        }
 
4713
                        else
 
4714
                        {
 
4715
                                if( response.Error.Code == 2 )
 
4716
                                        return false;
 
4717
                                else
 
4718
                                        throw new FlickrApiException(response.Error);
 
4719
                        }
 
4720
                }
 
4721
 
 
4722
                /// <summary>
 
4723
                /// Gets a list of photos that do not contain geo location information.
 
4724
                /// </summary>
 
4725
                /// <returns>A list of photos that do not contain location information.</returns>
 
4726
                public Photos PhotosGetWithoutGeoData()
 
4727
                {
 
4728
                        PartialSearchOptions options = new PartialSearchOptions();
 
4729
                        return PhotosGetWithoutGeoData(options);
 
4730
                }
 
4731
 
 
4732
                /// <summary>
 
4733
                /// Gets a list of photos that do not contain geo location information.
 
4734
                /// </summary>
 
4735
                /// <param name="options">A limited set of options are supported.</param>
 
4736
                /// <returns>A list of photos that do not contain location information.</returns>
 
4737
                public Photos PhotosGetWithoutGeoData(PartialSearchOptions options)
 
4738
                {
 
4739
                        Hashtable parameters = new Hashtable();
 
4740
                        parameters.Add("method", "flickr.photos.getWithoutGeoData");
 
4741
                        Utils.PartialOptionsIntoArray(options, parameters);
 
4742
 
 
4743
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4744
                        if( response.Status == ResponseStatus.OK )
 
4745
                        {
 
4746
                                return response.Photos;
 
4747
                        }
 
4748
                        else
 
4749
                        {
 
4750
                                throw new FlickrApiException(response.Error);
 
4751
                        }
 
4752
                }
 
4753
 
 
4754
                /// <summary>
 
4755
                /// Gets a list of photos that do not contain geo location information.
 
4756
                /// </summary>
 
4757
                /// <param name="options">A limited set of options are supported.
 
4758
                /// Unsupported arguments are ignored.
 
4759
                /// See http://www.flickr.com/services/api/flickr.photos.getWithGeoData.html for supported properties.</param>
 
4760
                /// <returns>A list of photos that do not contain location information.</returns>
 
4761
                [Obsolete("Use the PartialSearchOptions instead")]
 
4762
                public Photos PhotosGetWithoutGeoData(PhotoSearchOptions options)
 
4763
                {
 
4764
                        PartialSearchOptions newOptions = new PartialSearchOptions(options);
 
4765
                        return PhotosGetWithoutGeoData(newOptions);
 
4766
                }
 
4767
 
 
4768
                /// <summary>
 
4769
                /// Gets a list of photos that contain geo location information.
 
4770
                /// </summary>
 
4771
                /// <remarks>
 
4772
                /// Note, this method doesn't actually return the location information with the photos,
 
4773
                /// unless you specify the <see cref="PhotoSearchExtras.Geo"/> option in the <c>extras</c> parameter.
 
4774
                /// </remarks>
 
4775
                /// <returns>A list of photos that contain Location information.</returns>
 
4776
                public Photos PhotosGetWithGeoData()
 
4777
                {
 
4778
                        PartialSearchOptions options = new PartialSearchOptions();
 
4779
                        return PhotosGetWithGeoData(options);
 
4780
                }
 
4781
 
 
4782
                /// <summary>
 
4783
                /// Gets a list of photos that contain geo location information.
 
4784
                /// </summary>
 
4785
                /// <remarks>
 
4786
                /// Note, this method doesn't actually return the location information with the photos,
 
4787
                /// unless you specify the <see cref="PhotoSearchExtras.Geo"/> option in the <c>extras</c> parameter.
 
4788
                /// </remarks>
 
4789
                /// <param name="options">A limited set of options are supported.
 
4790
                /// Unsupported arguments are ignored.
 
4791
                /// See http://www.flickr.com/services/api/flickr.photos.getWithGeoData.html for supported properties.</param>
 
4792
                /// <returns>A list of photos that contain Location information.</returns>
 
4793
                [Obsolete("Use the new PartialSearchOptions instead")]
 
4794
                public Photos PhotosGetWithGeoData(PhotoSearchOptions options)
 
4795
                {
 
4796
                        PartialSearchOptions newOptions = new PartialSearchOptions(options);
 
4797
                        return PhotosGetWithGeoData(newOptions);
 
4798
                }
 
4799
 
 
4800
                /// <summary>
 
4801
                /// Gets a list of photos that contain geo location information.
 
4802
                /// </summary>
 
4803
                /// <remarks>
 
4804
                /// Note, this method doesn't actually return the location information with the photos,
 
4805
                /// unless you specify the <see cref="PhotoSearchExtras.Geo"/> option in the <c>extras</c> parameter.
 
4806
                /// </remarks>
 
4807
                /// <param name="options">The options to filter/sort the results by.</param>
 
4808
                /// <returns>A list of photos that contain Location information.</returns>
 
4809
                public Photos PhotosGetWithGeoData(PartialSearchOptions options)
 
4810
                {
 
4811
                        Hashtable parameters = new Hashtable();
 
4812
                        parameters.Add("method", "flickr.photos.getWithGeoData");
 
4813
                        Utils.PartialOptionsIntoArray(options, parameters);
 
4814
 
 
4815
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4816
                        if( response.Status == ResponseStatus.OK )
 
4817
                        {
 
4818
                                return response.Photos;
 
4819
                        }
 
4820
                        else
 
4821
                        {
 
4822
                                throw new FlickrApiException(response.Error);
 
4823
                        }
 
4824
                }
 
4825
 
 
4826
                /// <summary>
 
4827
                /// Get permissions for a photo.
 
4828
                /// </summary>
 
4829
                /// <param name="photoId">The id of the photo to get permissions for.</param>
 
4830
                /// <returns>An instance of the <see cref="PhotoPermissions"/> class containing the permissions of the specified photo.</returns>
 
4831
                public GeoPermissions PhotosGeoGetPerms(string photoId)
 
4832
                {
 
4833
                        Hashtable parameters = new Hashtable();
 
4834
                        parameters.Add("method", "flickr.photos.geo.getPerms");
 
4835
                        parameters.Add("photo_id", photoId);
 
4836
 
 
4837
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4838
 
 
4839
                        if( response.Status == ResponseStatus.OK )
 
4840
                        {
 
4841
                                return new GeoPermissions(response.AllElements[0]);
 
4842
                        }
 
4843
                        else
 
4844
                        {
 
4845
                                throw new FlickrApiException(response.Error);
 
4846
                        }
 
4847
                }
 
4848
 
 
4849
                /// <summary>
 
4850
                /// Set the permission for who can see geotagged photos on Flickr.
 
4851
                /// </summary>
 
4852
                /// <param name="photoId">The ID of the photo permissions to update.</param>
 
4853
                /// <param name="IsPublic"></param>
 
4854
                /// <param name="IsContact"></param>
 
4855
                /// <param name="IsFamily"></param>
 
4856
                /// <param name="IsFriend"></param>
 
4857
                public void PhotosGeoSetPerms(string photoId, bool IsPublic, bool IsContact, bool IsFamily, bool IsFriend)
 
4858
                {
 
4859
                        Hashtable parameters = new Hashtable();
 
4860
                        parameters.Add("method", "flickr.photos.geo.setPerms");
 
4861
                        parameters.Add("photo_id", photoId);
 
4862
                        parameters.Add("is_public", IsPublic?"1":"0");
 
4863
                        parameters.Add("is_contact", IsContact?"1":"0");
 
4864
                        parameters.Add("is_friend", IsFriend?"1":"0");
 
4865
                        parameters.Add("is_family", IsFamily?"1":"0");
 
4866
 
 
4867
                        FlickrNet.Response response = GetResponseNoCache(parameters);
 
4868
 
 
4869
                        if( response.Status == ResponseStatus.OK )
 
4870
                        {
 
4871
                                return;
 
4872
                        }
 
4873
                        else
 
4874
                        {
 
4875
                                throw new FlickrApiException(response.Error);
 
4876
                        }
 
4877
                }
 
4878
 
 
4879
 
 
4880
                #endregion
 
4881
 
 
4882
                #region [ Tests ]
 
4883
                /// <summary>
 
4884
                /// Can be used to call unsupported methods in the Flickr API.
 
4885
                /// </summary>
 
4886
                /// <remarks>
 
4887
                /// Use of this method is not supported.
 
4888
                /// The way the FlickrNet API Library works may mean that some methods do not return an expected result
 
4889
                /// when using this method.
 
4890
                /// </remarks>
 
4891
                /// <param name="method">The method name, e.g. "flickr.test.null".</param>
 
4892
                /// <param name="parameters">A list of parameters. Note, api_key is added by default and is not included. Can be null.</param>
 
4893
                /// <returns>An array of <see cref="XmlElement"/> instances which is the expected response.</returns>
 
4894
                public XmlElement[] TestGeneric(string method, NameValueCollection parameters)
 
4895
                {
 
4896
                        Hashtable _parameters = new Hashtable();
 
4897
                        if( parameters != null )
 
4898
                        {
 
4899
                                foreach(string key in parameters.AllKeys)
 
4900
                                {
 
4901
                                        _parameters.Add(key, parameters[key]);
 
4902
                                }
 
4903
                        }
 
4904
                        _parameters.Add("method", method);
 
4905
 
 
4906
                        FlickrNet.Response response = GetResponseNoCache(_parameters);
 
4907
 
 
4908
                        if( response.Status == ResponseStatus.OK )
 
4909
                        {
 
4910
                                return response.AllElements;
 
4911
                        }
 
4912
                        else
 
4913
                        {
 
4914
                                throw new FlickrApiException(response.Error);
 
4915
                        }
 
4916
                }
 
4917
                /// <summary>
 
4918
                /// Runs the flickr.test.echo method and returned an array of <see cref="XmlElement"/> items.
 
4919
                /// </summary>
 
4920
                /// <param name="echoParameter">The parameter to pass to the method.</param>
 
4921
                /// <param name="echoValue">The value to pass to the method with the parameter.</param>
 
4922
                /// <returns>An array of <see cref="XmlElement"/> items.</returns>
 
4923
                /// <remarks>
 
4924
                /// The APi Key has been removed from the returned array and will not be shown.
 
4925
                /// </remarks>
 
4926
                /// <example>
 
4927
                /// <code>
 
4928
                /// XmlElement[] elements = flickr.TestEcho("&amp;param=value");
 
4929
                /// foreach(XmlElement element in elements)
 
4930
                /// {
 
4931
                ///             if( element.Name = "method" )
 
4932
                ///                     Console.WriteLine("Method = " + element.InnerXml);
 
4933
                ///             if( element.Name = "param" )
 
4934
                ///                     Console.WriteLine("Param = " + element.InnerXml);
 
4935
                /// }
 
4936
                /// </code>
 
4937
                /// </example>
 
4938
                public XmlElement[] TestEcho(string echoParameter, string echoValue)
 
4939
                {
 
4940
                        Hashtable parameters = new Hashtable();
 
4941
                        parameters.Add("method", "flickr.test.echo");
 
4942
                        parameters.Add("api_key", _apiKey);
 
4943
                        if( echoParameter != null && echoParameter.Length > 0 )
 
4944
                        {
 
4945
                                parameters.Add(echoParameter, echoValue);
 
4946
                        }
 
4947
 
 
4948
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4949
 
 
4950
                        if( response.Status == ResponseStatus.OK )
 
4951
                        {
 
4952
                                // Remove the api_key element from the array.
 
4953
                                XmlElement[] elements = new XmlElement[response.AllElements.Length - 1];
 
4954
                                int c = 0;
 
4955
                                foreach(XmlElement element in response.AllElements)
 
4956
                                {
 
4957
                                        if(element.Name != "api_key" )
 
4958
                                                elements[c++] = element;
 
4959
                                }
 
4960
                                return elements;
 
4961
                        }
 
4962
                        else
 
4963
                        {
 
4964
                                throw new FlickrApiException(response.Error);
 
4965
                        }
 
4966
                }
 
4967
 
 
4968
                /// <summary>
 
4969
                /// Test the logged in state of the current Filckr object.
 
4970
                /// </summary>
 
4971
                /// <returns>The <see cref="FoundUser"/> object containing the username and userid of the current user.</returns>
 
4972
                public FoundUser TestLogin()
 
4973
                {
 
4974
                        Hashtable parameters = new Hashtable();
 
4975
                        parameters.Add("method", "flickr.test.login");
 
4976
 
 
4977
                        FlickrNet.Response response = GetResponseCache(parameters);
 
4978
 
 
4979
                        if( response.Status == ResponseStatus.OK )
 
4980
                        {
 
4981
                                return new FoundUser(response.AllElements[0]);
 
4982
                        }
 
4983
                        else
 
4984
                        {
 
4985
                                throw new FlickrApiException(response.Error);
 
4986
                        }
 
4987
                }
 
4988
                #endregion
 
4989
 
 
4990
                #region [ Urls ]
 
4991
                /// <summary>
 
4992
                /// Returns the url to a group's page.
 
4993
                /// </summary>
 
4994
                /// <param name="groupId">The NSID of the group to fetch the url for.</param>
 
4995
                /// <returns>An instance of the <see cref="Uri"/> class containing the URL of the group page.</returns>
 
4996
                public Uri UrlsGetGroup(string groupId)
 
4997
                {
 
4998
                        Hashtable parameters = new Hashtable();
 
4999
                        parameters.Add("method", "flickr.urls.getGroup");
 
5000
                        parameters.Add("api_key", _apiKey);
 
5001
                        parameters.Add("group_id", groupId);
 
5002
 
 
5003
                        FlickrNet.Response response = GetResponseCache(parameters);
 
5004
 
 
5005
                        if( response.Status == ResponseStatus.OK )
 
5006
                        {
 
5007
                                if( response.AllElements[0] != null && response.AllElements[0].Attributes["url"] != null )
 
5008
                                        return new Uri(response.AllElements[0].Attributes["url"].Value);
 
5009
                                else
 
5010
                                        return null;
 
5011
                        }
 
5012
                        else
 
5013
                        {
 
5014
                                throw new FlickrApiException(response.Error);
 
5015
                        }
 
5016
                }
 
5017
 
 
5018
                /// <summary>
 
5019
                /// Returns the url to a user's photos.
 
5020
                /// </summary>
 
5021
                /// <returns>An instance of the <see cref="Uri"/> class containing the URL for the users photos.</returns>
 
5022
                public Uri UrlsGetUserPhotos()
 
5023
                {
 
5024
                        return UrlsGetUserPhotos(null);
 
5025
                }
 
5026
 
 
5027
                /// <summary>
 
5028
                /// Returns the url to a user's photos.
 
5029
                /// </summary>
 
5030
                /// <param name="userId">The NSID of the user to fetch the url for. If omitted, the calling user is assumed.</param>
 
5031
                /// <returns>The URL of the users photos.</returns>
 
5032
                public Uri UrlsGetUserPhotos(string userId)
 
5033
                {
 
5034
                        Hashtable parameters = new Hashtable();
 
5035
                        parameters.Add("method", "flickr.urls.getUserPhotos");
 
5036
                        if( userId != null && userId.Length > 0 ) parameters.Add("user_id", userId);
 
5037
 
 
5038
                        FlickrNet.Response response = GetResponseCache(parameters);
 
5039
 
 
5040
                        if( response.Status == ResponseStatus.OK )
 
5041
                        {
 
5042
                                if( response.AllElements[0] != null && response.AllElements[0].Attributes["url"] != null )
 
5043
                                        return new Uri(response.AllElements[0].Attributes["url"].Value);
 
5044
                                else
 
5045
                                        return null;
 
5046
                        }
 
5047
                        else
 
5048
                        {
 
5049
                                throw new FlickrApiException(response.Error);
 
5050
                        }
 
5051
                }
 
5052
 
 
5053
                /// <summary>
 
5054
                /// Returns the url to a user's profile.
 
5055
                /// </summary>
 
5056
                /// <returns>An instance of the <see cref="Uri"/> class containing the URL for the users profile.</returns>
 
5057
                public Uri UrlsGetUserProfile()
 
5058
                {
 
5059
                        return UrlsGetUserProfile(null);
 
5060
                }
 
5061
 
 
5062
                /// <summary>
 
5063
                /// Returns the url to a user's profile.
 
5064
                /// </summary>
 
5065
                /// <param name="userId">The NSID of the user to fetch the url for. If omitted, the calling user is assumed.</param>
 
5066
                /// <returns>An instance of the <see cref="Uri"/> class containing the URL for the users profile.</returns>
 
5067
                public Uri UrlsGetUserProfile(string userId)
 
5068
                {
 
5069
                        Hashtable parameters = new Hashtable();
 
5070
                        parameters.Add("method", "flickr.urls.getUserProfile");
 
5071
                        if( userId != null && userId.Length > 0 ) parameters.Add("user_id", userId);
 
5072
 
 
5073
                        FlickrNet.Response response = GetResponseCache(parameters);
 
5074
 
 
5075
                        if( response.Status == ResponseStatus.OK )
 
5076
                        {
 
5077
                                if( response.AllElements[0] != null && response.AllElements[0].Attributes["url"] != null )
 
5078
                                        return new Uri(response.AllElements[0].Attributes["url"].Value);
 
5079
                                else
 
5080
                                        return null;
 
5081
                        }
 
5082
                        else
 
5083
                        {
 
5084
                                throw new FlickrApiException(response.Error);
 
5085
                        }
 
5086
                }
 
5087
 
 
5088
                /// <summary>
 
5089
                /// Returns a group NSID, given the url to a group's page or photo pool.
 
5090
                /// </summary>
 
5091
                /// <param name="urlToFind">The url to the group's page or photo pool.</param>
 
5092
                /// <returns>The ID of the group at the specified URL on success, a null reference (Nothing in Visual Basic) if the group cannot be found.</returns>
 
5093
                public string UrlsLookupGroup(string urlToFind)
 
5094
                {
 
5095
                        Hashtable parameters = new Hashtable();
 
5096
                        parameters.Add("method", "flickr.urls.lookupGroup");
 
5097
                        parameters.Add("api_key", _apiKey);
 
5098
                        parameters.Add("url", urlToFind);
 
5099
 
 
5100
                        FlickrNet.Response response = GetResponseCache(parameters);
 
5101
 
 
5102
                        if( response.Status == ResponseStatus.OK )
 
5103
                        {
 
5104
                                if( response.AllElements[0] != null && response.AllElements[0].Attributes["id"] != null )
 
5105
                                {
 
5106
                                        return response.AllElements[0].Attributes["id"].Value;
 
5107
                                }
 
5108
                                else
 
5109
                                {
 
5110
                                        return null;
 
5111
                                }
 
5112
                        }
 
5113
                        else
 
5114
                        {
 
5115
                                if( response.Error.Code == 1 )
 
5116
                                        return null;
 
5117
                                else
 
5118
                                        throw new FlickrApiException(response.Error);
 
5119
                        }
 
5120
                }
 
5121
 
 
5122
                /// <summary>
 
5123
                /// Returns a user NSID, given the url to a user's photos or profile.
 
5124
                /// </summary>
 
5125
                /// <param name="urlToFind">Thr url to the user's profile or photos page.</param>
 
5126
                /// <returns>An instance of the <see cref="FoundUser"/> class containing the users ID and username.</returns>
 
5127
                public FoundUser UrlsLookupUser(string urlToFind)
 
5128
                {
 
5129
                        Hashtable parameters = new Hashtable();
 
5130
                        parameters.Add("method", "flickr.urls.lookupUser");
 
5131
                        parameters.Add("api_key", _apiKey);
 
5132
                        parameters.Add("url", urlToFind);
 
5133
 
 
5134
                        FlickrNet.Response response = GetResponseCache(parameters);
 
5135
 
 
5136
                        if( response.Status == ResponseStatus.OK )
 
5137
                        {
 
5138
                                return new FoundUser(response.AllElements[0]);
 
5139
                        }
 
5140
                        else
 
5141
                        {
 
5142
                                throw new FlickrApiException(response.Error);
 
5143
                        }
 
5144
                }
 
5145
                #endregion
 
5146
 
 
5147
                #region [ Reflection ]
 
5148
                /// <summary>
 
5149
                /// Gets an array of supported method names for Flickr.
 
5150
                /// </summary>
 
5151
                /// <remarks>
 
5152
                /// Note: Not all methods might be supported by the FlickrNet Library.</remarks>
 
5153
                /// <returns></returns>
 
5154
                public string[] ReflectionGetMethods()
 
5155
                {
 
5156
                        Hashtable parameters = new Hashtable();
 
5157
                        parameters.Add("method", "flickr.reflection.getMethods");
 
5158
                        parameters.Add("api_key", _apiKey);
 
5159
 
 
5160
                        FlickrNet.Response response = GetResponseCache(parameters);
 
5161
 
 
5162
                        if( response.Status == ResponseStatus.OK )
 
5163
                        {
 
5164
                                return Methods.GetMethods(response.AllElements[0]);
 
5165
                        }
 
5166
                        else
 
5167
                        {
 
5168
                                throw new FlickrApiException(response.Error);
 
5169
                        }
 
5170
                }
 
5171
 
 
5172
                /// <summary>
 
5173
                /// Gets the method details for a given method.
 
5174
                /// </summary>
 
5175
                /// <param name="methodName">The name of the method to retrieve.</param>
 
5176
                /// <returns>Returns a <see cref="Method"/> instance for the given method name.</returns>
 
5177
                public Method ReflectionGetMethodInfo(string methodName)
 
5178
                {
 
5179
                        Hashtable parameters = new Hashtable();
 
5180
                        parameters.Add("method", "flickr.reflection.getMethodInfo");
 
5181
                        parameters.Add("api_key", _apiKey);
 
5182
                        parameters.Add("method_name", methodName);
 
5183
 
 
5184
                        FlickrNet.Response response = GetResponseCache(parameters);
 
5185
 
 
5186
                        if( response.Status == ResponseStatus.OK )
 
5187
                        {
 
5188
                                return response.Method;
 
5189
                        }
 
5190
                        else
 
5191
                        {
 
5192
                                throw new FlickrApiException(response.Error);
 
5193
                        }
 
5194
                }
 
5195
 
 
5196
                #endregion
 
5197
 
 
5198
                #region [ MD5 Hash ]
 
5199
                private static string Md5Hash(string unhashed)
 
5200
                {
 
5201
                        System.Security.Cryptography.MD5CryptoServiceProvider csp = new System.Security.Cryptography.MD5CryptoServiceProvider();
 
5202
                        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(unhashed);
 
5203
                        byte[] hashedBytes = csp.ComputeHash(bytes, 0, bytes.Length);
 
5204
                        return BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
 
5205
                }
 
5206
                #endregion
 
5207
 
 
5208
                private void CheckApiKey()
 
5209
                {
 
5210
                        if( ApiKey == null || ApiKey.Length == 0 )
 
5211
                                throw new ApiKeyRequiredException();
 
5212
                }
 
5213
                private void CheckRequiresAuthentication()
 
5214
                {
 
5215
                        CheckApiKey();
 
5216
 
 
5217
                        if( ApiSecret == null || ApiSecret.Length == 0 )
 
5218
                                throw new SignatureRequiredException();
 
5219
                        if( AuthToken == null || AuthToken.Length == 0 )
 
5220
                                throw new AuthenticationRequiredException();
 
5221
 
 
5222
                }
 
5223
        }
 
5224
 
 
5225
}