PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ShareX.UploadersLib/ImageUploaders/FlickrUploader.cs

https://gitlab.com/billyprice1/ShareX
C# | 387 lines | 242 code | 71 blank | 74 comment | 20 complexity | f13b9d5c3cf8c399b78f1ecf18e5c5a8 MD5 | raw file
  1. #region License Information (GPL v3)
  2. /*
  3. ShareX - A program that allows you to take screenshots and share any file type
  4. Copyright (c) 2007-2016 ShareX Team
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. Optionally you can also view the license at <http://www.gnu.org/licenses/>.
  17. */
  18. #endregion License Information (GPL v3)
  19. using ShareX.HelpersLib;
  20. using ShareX.UploadersLib.Properties;
  21. using System;
  22. using System.Collections.Generic;
  23. using System.ComponentModel;
  24. using System.Drawing;
  25. using System.IO;
  26. using System.Linq;
  27. using System.Windows.Forms;
  28. using System.Xml.Linq;
  29. namespace ShareX.UploadersLib.ImageUploaders
  30. {
  31. public class FlickrImageUploaderService : ImageUploaderService
  32. {
  33. public override ImageDestination EnumValue { get; } = ImageDestination.Flickr;
  34. public override Icon ServiceIcon => Resources.Flickr;
  35. public override bool CheckConfig(UploadersConfig config)
  36. {
  37. return !string.IsNullOrEmpty(config.FlickrAuthInfo.Token);
  38. }
  39. public override GenericUploader CreateUploader(UploadersConfig config, TaskReferenceHelper taskInfo)
  40. {
  41. return new FlickrUploader(APIKeys.FlickrKey, APIKeys.FlickrSecret, config.FlickrAuthInfo, config.FlickrSettings);
  42. }
  43. public override TabPage GetUploadersConfigTabPage(UploadersConfigForm form) => form.tpFlickr;
  44. }
  45. public class FlickrUploader : ImageUploader
  46. {
  47. private string API_Key, API_Secret;
  48. private const string API_URL = "https://api.flickr.com/services/rest/";
  49. private const string API_Auth_URL = "https://www.flickr.com/services/auth/";
  50. public FlickrAuthInfo Auth = new FlickrAuthInfo();
  51. public FlickrSettings Settings = new FlickrSettings();
  52. public string Frob;
  53. public FlickrUploader(string key, string secret)
  54. {
  55. API_Key = key;
  56. API_Secret = secret;
  57. }
  58. public FlickrUploader(string key, string secret, FlickrAuthInfo auth, FlickrSettings settings) : this(key, secret)
  59. {
  60. Auth = auth;
  61. Settings = settings;
  62. }
  63. #region Auth
  64. /// <summary>
  65. /// Returns the credentials attached to an authentication token.
  66. /// http://www.flickr.com/services/api/flickr.auth.checkToken.html
  67. /// </summary>
  68. public FlickrAuthInfo CheckToken(string token)
  69. {
  70. Dictionary<string, string> args = new Dictionary<string, string>();
  71. args.Add("method", "flickr.auth.checkToken");
  72. args.Add("api_key", API_Key);
  73. args.Add("auth_token", token);
  74. args.Add("api_sig", GetAPISig(args));
  75. string response = SendRequest(HttpMethod.POST, API_URL, args);
  76. Auth = new FlickrAuthInfo(ParseResponse(response, "auth"));
  77. return Auth;
  78. }
  79. /// <summary>
  80. /// Returns a frob to be used during authentication.
  81. /// http://www.flickr.com/services/api/flickr.auth.getFrob.html
  82. /// </summary>
  83. public string GetFrob()
  84. {
  85. Dictionary<string, string> args = new Dictionary<string, string>();
  86. args.Add("method", "flickr.auth.getFrob");
  87. args.Add("api_key", API_Key);
  88. args.Add("api_sig", GetAPISig(args));
  89. string response = SendRequest(HttpMethod.POST, API_URL, args);
  90. XElement eFrob = ParseResponse(response, "frob");
  91. if (eFrob == null)
  92. {
  93. string errorMessage = ToErrorString();
  94. if (string.IsNullOrEmpty(errorMessage))
  95. {
  96. throw new Exception("getFrob failed.");
  97. }
  98. throw new Exception(errorMessage);
  99. }
  100. Frob = eFrob.Value;
  101. return Frob;
  102. }
  103. /// <summary>
  104. /// Get the full authentication token for a mini-token.
  105. /// http://www.flickr.com/services/api/flickr.auth.getFullToken.html
  106. /// </summary>
  107. public FlickrAuthInfo GetFullToken(string frob)
  108. {
  109. Dictionary<string, string> args = new Dictionary<string, string>();
  110. args.Add("method", "flickr.auth.getFullToken");
  111. args.Add("api_key", API_Key);
  112. args.Add("mini_token", frob);
  113. args.Add("api_sig", GetAPISig(args));
  114. string response = SendRequest(HttpMethod.POST, API_URL, args);
  115. Auth = new FlickrAuthInfo(ParseResponse(response, "auth"));
  116. return Auth;
  117. }
  118. /// <summary>
  119. /// Returns the auth token for the given frob, if one has been attached.
  120. /// http://www.flickr.com/services/api/flickr.auth.getToken.html
  121. /// </summary>
  122. /// <returns></returns>
  123. public FlickrAuthInfo GetToken(string frob)
  124. {
  125. Dictionary<string, string> args = new Dictionary<string, string>();
  126. args.Add("method", "flickr.auth.getToken");
  127. args.Add("api_key", API_Key);
  128. args.Add("frob", frob);
  129. args.Add("api_sig", GetAPISig(args));
  130. string response = SendRequest(HttpMethod.POST, API_URL, args);
  131. Auth = new FlickrAuthInfo(ParseResponse(response, "auth"));
  132. return Auth;
  133. }
  134. public FlickrAuthInfo GetToken()
  135. {
  136. return GetToken(Frob);
  137. }
  138. public string GetAuthLink()
  139. {
  140. return GetAuthLink(FlickrPermission.Write);
  141. }
  142. public string GetAuthLink(FlickrPermission perm)
  143. {
  144. if (!string.IsNullOrEmpty(Frob))
  145. {
  146. Dictionary<string, string> args = new Dictionary<string, string>();
  147. args.Add("api_key", API_Key);
  148. args.Add("perms", perm.ToString().ToLowerInvariant());
  149. args.Add("frob", Frob);
  150. args.Add("api_sig", GetAPISig(args));
  151. return string.Format("{0}?{1}", API_Auth_URL, string.Join("&", args.Select(x => x.Key + "=" + x.Value).ToArray()));
  152. }
  153. return null;
  154. }
  155. public string GetPhotosLink(string userID)
  156. {
  157. return URLHelpers.CombineURL("https://www.flickr.com/photos", userID);
  158. }
  159. public string GetPhotosLink()
  160. {
  161. return GetPhotosLink(Auth.UserID);
  162. }
  163. #endregion Auth
  164. #region Helpers
  165. private string GetAPISig(Dictionary<string, string> args)
  166. {
  167. return TranslatorHelper.TextToHash(args.OrderBy(x => x.Key).Aggregate(API_Secret, (x, x2) => x + x2.Key + x2.Value), HashType.MD5);
  168. }
  169. private XElement ParseResponse(string response, string field)
  170. {
  171. if (!string.IsNullOrEmpty(response))
  172. {
  173. XDocument xdoc = XDocument.Parse(response);
  174. XElement xele = xdoc.Element("rsp");
  175. if (xele != null)
  176. {
  177. switch (xele.GetAttributeFirstValue("status", "stat"))
  178. {
  179. case "ok":
  180. return xele.Element(field);
  181. case "fail":
  182. XElement err = xele.Element("err");
  183. string code = err.GetAttributeValue("code");
  184. string msg = err.GetAttributeValue("msg");
  185. // throw new Exception(string.Format("Code: {0}, Message: {1}", code, msg));
  186. Errors.Add(msg);
  187. break;
  188. }
  189. }
  190. }
  191. return null;
  192. }
  193. #endregion Helpers
  194. public override UploadResult Upload(Stream stream, string fileName)
  195. {
  196. Dictionary<string, string> args = new Dictionary<string, string>();
  197. args.Add("api_key", API_Key);
  198. args.Add("auth_token", Auth.Token);
  199. if (!string.IsNullOrEmpty(Settings.Title)) args.Add("title", Settings.Title);
  200. if (!string.IsNullOrEmpty(Settings.Description)) args.Add("description", Settings.Description);
  201. if (!string.IsNullOrEmpty(Settings.Tags)) args.Add("tags", Settings.Tags);
  202. if (!string.IsNullOrEmpty(Settings.IsPublic)) args.Add("is_public", Settings.IsPublic);
  203. if (!string.IsNullOrEmpty(Settings.IsFriend)) args.Add("is_friend", Settings.IsFriend);
  204. if (!string.IsNullOrEmpty(Settings.IsFamily)) args.Add("is_family", Settings.IsFamily);
  205. if (!string.IsNullOrEmpty(Settings.SafetyLevel)) args.Add("safety_level", Settings.SafetyLevel);
  206. if (!string.IsNullOrEmpty(Settings.ContentType)) args.Add("content_type", Settings.ContentType);
  207. if (!string.IsNullOrEmpty(Settings.Hidden)) args.Add("hidden", Settings.Hidden);
  208. args.Add("api_sig", GetAPISig(args));
  209. UploadResult result = UploadData(stream, "https://up.flickr.com/services/upload/", fileName, "photo", args);
  210. if (result.IsSuccess)
  211. {
  212. XElement xele = ParseResponse(result.Response, "photoid");
  213. if (null != xele)
  214. {
  215. string photoid = xele.Value;
  216. string url = URLHelpers.CombineURL(GetPhotosLink(), photoid);
  217. result.URL = URLHelpers.CombineURL(url, "sizes/o");
  218. }
  219. }
  220. return result;
  221. }
  222. }
  223. public class FlickrAuthInfo
  224. {
  225. [Description("Token string"), ReadOnly(true), PasswordPropertyText(true)]
  226. public string Token { get; set; }
  227. [Description("Permission"), ReadOnly(true)]
  228. public string Permission { get; set; }
  229. [Description("User ID that can be used in a URL")]
  230. public string UserID { get; set; }
  231. [Description("Your Flickr username"), ReadOnly(true)]
  232. public string Username { get; set; }
  233. [Description("Full name"), ReadOnly(true)]
  234. public string Fullname { get; set; }
  235. public FlickrAuthInfo()
  236. {
  237. }
  238. public FlickrAuthInfo(XElement element)
  239. {
  240. Token = element.GetElementValue("token");
  241. Permission = element.GetElementValue("perms");
  242. XElement user = element.Element("user");
  243. UserID = user.GetAttributeValue("nsid");
  244. Username = user.GetAttributeValue("username");
  245. Fullname = user.GetAttributeValue("fullname");
  246. }
  247. }
  248. public class FlickrSettings
  249. {
  250. /// <summary>
  251. /// The title of the photo.
  252. /// </summary>
  253. [Description("The title of the photo.")]
  254. public string Title { get; set; }
  255. /// <summary>
  256. /// A description of the photo. May contain some limited HTML.
  257. /// </summary>
  258. [Description("A description of the photo. May contain some limited HTML.")]
  259. public string Description { get; set; }
  260. /// <summary>
  261. /// A space-seperated list of tags to apply to the photo.
  262. /// </summary>
  263. [Description("A space-seperated list of tags to apply to the photo.")]
  264. public string Tags { get; set; }
  265. /// <summary>
  266. /// Set to 0 for no, 1 for yes. Specifies who can view the photo.
  267. /// </summary>
  268. [Description("Set to 0 for no, 1 for yes. Specifies who can view the photo.")]
  269. public string IsPublic { get; set; }
  270. /// <summary>
  271. /// Set to 0 for no, 1 for yes. Specifies who can view the photo.
  272. /// </summary>
  273. [Description("Set to 0 for no, 1 for yes. Specifies who can view the photo.")]
  274. public string IsFriend { get; set; }
  275. /// <summary>
  276. /// Set to 0 for no, 1 for yes. Specifies who can view the photo.
  277. /// </summary>
  278. [Description("Set to 0 for no, 1 for yes. Specifies who can view the photo.")]
  279. public string IsFamily { get; set; }
  280. /// <summary>
  281. /// Set to 1 for Safe, 2 for Moderate, or 3 for Restricted.
  282. /// </summary>
  283. [Description("Set to 1 for Safe, 2 for Moderate, or 3 for Restricted.")]
  284. public string SafetyLevel { get; set; }
  285. /// <summary>
  286. /// Set to 1 for Photo, 2 for Screenshot, or 3 for Other.
  287. /// </summary>
  288. [Description("Set to 1 for Photo, 2 for Screenshot, or 3 for Other.")]
  289. public string ContentType { get; set; }
  290. /// <summary>
  291. /// Set to 1 to keep the photo in global search results, 2 to hide from public searches.
  292. /// </summary>
  293. [Description("Set to 1 to keep the photo in global search results, 2 to hide from public searches.")]
  294. public string Hidden { get; set; }
  295. }
  296. public enum FlickrPermission
  297. {
  298. None,
  299. /// <summary>
  300. /// Permission to read private information
  301. /// </summary>
  302. Read,
  303. /// <summary>
  304. /// Permission to add, edit and delete photo metadata (includes 'read')
  305. /// </summary>
  306. Write,
  307. /// <summary>
  308. /// Permission to delete photos (includes 'write' and 'read')
  309. /// </summary>
  310. Delete
  311. }
  312. }