├── JodelAPI ├── JodelAPI │ ├── packages.config │ ├── Json │ │ ├── Request │ │ │ ├── JsonRequestRefreshAccessToken.cs │ │ │ ├── JsonRequestUpDownVote.cs │ │ │ ├── JsonRequest.cs │ │ │ ├── JsonRequestRecommendedChannels.cs │ │ │ ├── JsonRequestFollowedChannelMeta.cs │ │ │ ├── JsonRequestPostsLocationCombo.cs │ │ │ ├── JsonRequestGenerateAccessToken.cs │ │ │ ├── JsonRequestSetLocation.cs │ │ │ └── JsonRequestPostJodel.cs │ │ └── Response │ │ │ ├── JsonKarma.cs │ │ │ ├── JsonRefreshTokens.cs │ │ │ ├── JsonCaptcha.cs │ │ │ ├── JsonPostJodel.cs │ │ │ ├── JsonRecommendedChannels.cs │ │ │ ├── JsonTokens.cs │ │ │ ├── JsonFollowedChannelsMeta.cs │ │ │ ├── JsonModeration.cs │ │ │ ├── JsonPostDetail.cs │ │ │ ├── JsonConfig.cs │ │ │ ├── JsonJodelsFirstRound.cs │ │ │ ├── JsonMyPins.cs │ │ │ ├── JsonMyJodels.cs │ │ │ ├── JsonJodelsLastRound.cs │ │ │ ├── JsonGCoordinates.cs │ │ │ ├── JsonMyVotes.cs │ │ │ ├── JsonMyComments.cs │ │ │ ├── JsonPostJodels.cs │ │ │ ├── JsonComments.cs │ │ │ └── JsonGetJodelsFromChannel.cs │ ├── Exceptions │ │ └── LocationNotFoundException.cs │ ├── Internal │ │ ├── Helpers.cs │ │ ├── Constants.cs │ │ ├── JodelWebClient.cs │ │ ├── Links.cs │ │ └── ApiCall.cs │ ├── Shared │ │ ├── JodelMainData.cs │ │ ├── Channel.cs │ │ ├── Location.cs │ │ ├── AccessToken.cs │ │ ├── User.cs │ │ ├── Captcha.cs │ │ └── JodelPost.cs │ ├── JodelAPI.nuspec │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── JodelApp.cs │ ├── JodelAPI.csproj │ ├── Jodel.cs │ └── Account.cs ├── JodelAPITests │ ├── JodelTests.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── JodelAPITests.csproj └── JodelAPI.sln ├── .gitattributes ├── README.md └── .gitignore /JodelAPI/JodelAPI/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestRefreshAccessToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Request 8 | { 9 | class JsonRequestRefreshAccessToken : JsonRequest 10 | { 11 | public string refresh_token { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonKarma.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Response 8 | { 9 | internal class JsonKarma 10 | { 11 | public class RootObject 12 | { 13 | public int karma { get; set; } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestUpDownVote.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Request 8 | { 9 | internal class JsonRequestUpDownVote:JsonRequest 10 | { 11 | #region 12 | 13 | public int reason_code { get; set; } = -1; 14 | 15 | #endregion 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonRefreshTokens.cs: -------------------------------------------------------------------------------- 1 | namespace JodelAPI.Json.Response 2 | { 3 | internal class JsonRefreshTokens 4 | { 5 | public class RootObject 6 | { 7 | public string access_token { get; set; } 8 | public string token_type { get; set; } 9 | public int expires_in { get; set; } 10 | public int expiration_date { get; set; } 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | 8 | namespace JodelAPI.Json.Request 9 | { 10 | public abstract class JsonRequest 11 | { 12 | public override string ToString() 13 | { 14 | return JsonConvert.SerializeObject(this); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonCaptcha.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Response 8 | { 9 | internal class JsonCaptcha 10 | { 11 | public class RootObject 12 | { 13 | public string key { get; set; } 14 | public string image_url { get; set; } 15 | public int image_size { get; set; } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestRecommendedChannels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Request 8 | { 9 | internal class JsonRequestRecommendedChannels : JsonRequest 10 | { 11 | #region Methods 12 | 13 | public override string ToString() 14 | { 15 | return "home: false"; 16 | } 17 | 18 | #endregion 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonPostJodel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Response 8 | { 9 | internal class JsonPostJodel 10 | { 11 | public class RootObject 12 | { 13 | #region Fields and Properties 14 | 15 | public long created_at { get; set; } 16 | public string post_id { get; set; } 17 | 18 | #endregion 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonRecommendedChannels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonRecommendedChannels 6 | { 7 | public class Recommended 8 | { 9 | public string channel { get; set; } 10 | public int followers { get; set; } 11 | public string image_url { get; set; } 12 | } 13 | 14 | public class RootObject 15 | { 16 | public List recommended { get; set; } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonTokens.cs: -------------------------------------------------------------------------------- 1 | namespace JodelAPI.Json.Response 2 | { 3 | internal class JsonTokens 4 | { 5 | public class RootObject 6 | { 7 | public string access_token { get; set; } 8 | public string refresh_token { get; set; } 9 | public string token_type { get; set; } 10 | public int expires_in { get; set; } 11 | public int expiration_date { get; set; } 12 | public string distinct_id { get; set; } 13 | public bool returning { get; set; } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Exceptions/LocationNotFoundException.cs: -------------------------------------------------------------------------------- 1 | [System.Serializable()] 2 | class LocationNotFoundException : System.Exception 3 | { 4 | public LocationNotFoundException() { } 5 | public LocationNotFoundException(string message) : base(message) { } 6 | public LocationNotFoundException(string message, System.Exception inner) : base(message, inner) { } 7 | 8 | // A constructor is needed for serialization when an 9 | // exception propagates from a remoting server to the client. 10 | protected LocationNotFoundException(System.Runtime.Serialization.SerializationInfo info, 11 | System.Runtime.Serialization.StreamingContext context) 12 | { } 13 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonFollowedChannelsMeta.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Response 8 | { 9 | internal class JsonFollowedChannelsMeta 10 | { 11 | public class Channel 12 | { 13 | public string channel { get; set; } 14 | public int followers { get; set; } 15 | public bool sponsored { get; set; } 16 | public bool unread { get; set; } 17 | } 18 | 19 | public class RootObject 20 | { 21 | public List channels { get; set; } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Internal/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Security.Cryptography; 4 | using static JodelAPI.Shared.JodelPost; 5 | 6 | namespace JodelAPI.Internal 7 | { 8 | internal static class Helpers 9 | { 10 | static Dictionary Colors = new Dictionary 11 | { 12 | { PostColor.Red, "DD5F5F" }, 13 | { PostColor.Orange, "FF9908" }, 14 | { PostColor.Yellow, "FFBA00" }, 15 | { PostColor.Blue, "DD5F5F" }, 16 | { PostColor.Bluegreyish, "8ABDB0" }, 17 | { PostColor.Green, "9EC41C" }, 18 | { PostColor.Random, "FFFFFF" } 19 | }; 20 | 21 | public static string GetColor(PostColor color) => Colors[color]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonModeration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonModeration 6 | { 7 | public class Queue 8 | { 9 | public string post_id { get; set; } 10 | public string message { get; set; } 11 | public int vote_count { get; set; } 12 | public string color { get; set; } 13 | public string user_handle { get; set; } 14 | public int task_id { get; set; } 15 | public int flag_count { get; set; } 16 | public string parent_id { get; set; } 17 | public int flag_reason { get; set; } 18 | } 19 | 20 | public class RootObject 21 | { 22 | public List posts { get; set; } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Shared/JodelMainData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Shared 8 | { 9 | public class JodelMainData 10 | { 11 | #region Fields and Properties 12 | 13 | public int Max { get; set; } 14 | 15 | public List RecentJodels { get; set; } 16 | public List RepliedJodels { get; set; } 17 | public List VotedJodels { get; set; } 18 | 19 | #endregion 20 | 21 | #region Constructor 22 | 23 | public JodelMainData() 24 | { 25 | RecentJodels = new List(); 26 | RepliedJodels = new List(); 27 | VotedJodels = new List(); 28 | } 29 | 30 | #endregion 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/JodelAPI.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JodelAPI 5 | 4.47.0.0 6 | Luca Marcelli 7 | Luca Marcelli 8 | https://github.com/ioncodes/JodelAPI 9 | false 10 | A .NET wrapper for the Jodel API. 11 | A .NET wrapper for the Jodel API. 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestFollowedChannelMeta.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | 8 | namespace JodelAPI.Json.Request 9 | { 10 | internal class JsonRequestFollowedChannelMeta : JsonRequest 11 | { 12 | #region Fields and Properties 13 | 14 | public Dictionary Values { get; set; } 15 | 16 | #endregion 17 | 18 | #region Constructor 19 | 20 | public JsonRequestFollowedChannelMeta() 21 | { 22 | Values = new Dictionary(); 23 | } 24 | 25 | #endregion 26 | 27 | #region Methods 28 | 29 | public override string ToString() 30 | { 31 | return JsonConvert.SerializeObject(Values); 32 | } 33 | 34 | #endregion 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestPostsLocationCombo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Request 8 | { 9 | internal class JsonRequestPostsLocationCombo : JsonRequest 10 | { 11 | #region Fields and Properties 12 | 13 | public string Lat { get; set; } 14 | public string Lng { get; set; } 15 | public bool Stickies { get; set; } 16 | public bool Home { get; set; } 17 | 18 | #endregion 19 | 20 | #region Methods 21 | 22 | public override string ToString() 23 | { 24 | return @"lat: " + Lat + "@\n" + 25 | @"lng: " + Lng + "@\n" + 26 | @"stickers: " + Stickies + @"\n" + 27 | @"home: " + Home; 28 | } 29 | 30 | #endregion 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestGenerateAccessToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Request 8 | { 9 | public class JsonRequestGenerateAccessToken : JsonRequest 10 | { 11 | public string device_uid { get; set; } 12 | public Location location { get; set; } 13 | public string client_id { get; set; } 14 | 15 | public class Location 16 | { 17 | public string City { get; set; } 18 | public double loc_accuracy { get; set; } 19 | public Coordinates loc_coordinates { get; set; } 20 | public string country { get; set; } 21 | 22 | public class Coordinates 23 | { 24 | public double lat { get; set; } 25 | public double lng { get; set; } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonPostDetail.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonPostDetail 6 | { 7 | public class LocCoordinates : JsonPostJodels.LocCoordinates { } 8 | 9 | public class Location : JsonPostJodels.Location { } 10 | 11 | public class ImageHeaders : JsonPostJodels.ImageHeaders { } 12 | 13 | public class Post : JsonPostJodels.Post 14 | { 15 | public string ancestor; 16 | public bool from_home; 17 | public int parent_creator; 18 | public string parent_id; 19 | public bool pinned; 20 | public string replier_mark; 21 | } 22 | 23 | public class RootObject 24 | { 25 | public Post details { get; set; } 26 | public string next { get; set; } 27 | public int remaining { get; set; } 28 | public List replies { get; set; } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Internal/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace JodelAPI.Internal 9 | { 10 | internal class Constants 11 | { 12 | // Key Values 13 | public const string Key = ""; 14 | public const string ClientId = "81e8a76e-1e02-4d17-9ba0-8a7020261b26"; 15 | public const string AppVersion = "4.47.0"; 16 | 17 | 18 | // Headers 19 | public static WebHeaderCollection Header = new WebHeaderCollection 20 | { 21 | {"Accept-Encoding", "gzip"}, 22 | {"User-Agent", "Jodel/" + AppVersion + " Dalvik/2.1.0 (Linux; U; Android 6.0.1; E6653 Build/32.2.A.0.305)"}, 23 | {"X-Client-Type", "android_" + AppVersion}, 24 | {"X-Api-Version", "0.2"} 25 | }; 26 | public static WebHeaderCollection JsonHeader = new WebHeaderCollection 27 | { 28 | {"Content-Type", "application/json; charset=UTF-8"} 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json 4 | { 5 | internal class JsonConfig 6 | { 7 | public class Experiment 8 | { 9 | public string name { get; set; } 10 | public string group { get; set; } 11 | public List features { get; set; } 12 | } 13 | 14 | public class RootObject 15 | { 16 | public bool moderator { get; set; } 17 | public object user_type { get; set; } 18 | public List experiments { get; set; } 19 | public List followed_channels { get; set; } 20 | public List followed_hashtags { get; set; } 21 | public int channels_follow_limit { get; set; } 22 | public bool triple_feed_enabled { get; set; } 23 | public string home_name { get; set; } 24 | public bool home_set { get; set; } 25 | public string location { get; set; } 26 | public bool verified { get; set; } 27 | 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestSetLocation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Request 8 | { 9 | internal class JsonRequestSetLocation : JsonRequest 10 | { 11 | #region Fields and Properties 12 | 13 | public Location location { get; set; } = new Location(); 14 | 15 | #endregion 16 | 17 | #region class 18 | 19 | public class Location 20 | { 21 | #region Fields and Properties 22 | 23 | public string city { get; set; } 24 | public string country { get; set; } 25 | public double loc_accuracy { get; set; } 26 | public Coordinates loc_coordinates { get; set; } = new Coordinates(); 27 | public string name { get; set; } 28 | #endregion 29 | } 30 | 31 | public class Coordinates 32 | { 33 | #region Fields and Properties 34 | 35 | public double lat { get; set; } 36 | public double lng { get; set; } 37 | 38 | #endregion 39 | } 40 | 41 | #endregion 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonJodelsFirstRound.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonJodelsFirstRound 6 | { 7 | public class LocCoordinates : JsonPostJodels.LocCoordinates { } 8 | 9 | public class Location : JsonPostJodels.Location { } 10 | 11 | public class ImageHeaders : JsonPostJodels.ImageHeaders { } 12 | 13 | public class Recent : JsonPostJodels.Post { } 14 | 15 | public class LocCoordinates2 : JsonPostJodels.LocCoordinates { } 16 | 17 | public class Location2 : JsonPostJodels.Location { } 18 | 19 | public class ImageHeaders2 : JsonPostJodels.ImageHeaders { } 20 | 21 | public class Replied : JsonPostJodels.Post { } 22 | 23 | public class LocCoordinates3 : JsonPostJodels.LocCoordinates { } 24 | 25 | public class Location3 : JsonPostJodels.Location { } 26 | 27 | public class Voted : JsonPostJodels.Post { } 28 | 29 | public class RootObject 30 | { 31 | public List recent { get; set; } 32 | public List replied { get; set; } 33 | public List voted { get; set; } 34 | public int max { get; set; } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPITests/JodelTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using JodelAPI; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using JodelAPI.Shared; 9 | 10 | namespace JodelAPI.Tests 11 | { 12 | [TestClass()] 13 | public class JodelTests 14 | { 15 | Jodel jodel = new Jodel("Zuerich Schweiz", "CH", "Zuerich"); 16 | 17 | 18 | [TestMethod()] 19 | public void GetKarmaTest() 20 | { 21 | int karma = jodel.GetKarma(); 22 | } 23 | 24 | [TestMethod()] 25 | public void GetRecommendedChannelsTest() 26 | { 27 | Assert.IsNotNull(jodel.GetRecommendedChannels()); 28 | } 29 | 30 | [TestMethod()] 31 | public void GetPostLocationComboTest() 32 | { 33 | Assert.IsNotNull(jodel.GetPostLocationCombo()); 34 | } 35 | 36 | [TestMethod()] 37 | public void ShareUrlProperty() 38 | { 39 | var combo = jodel.GetPostLocationCombo(); 40 | string url = combo.RecentJodels[1].ShareUrl; 41 | Uri uriResult; 42 | bool result = Uri.TryCreate(url, UriKind.Absolute, out uriResult) 43 | && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); 44 | Assert.IsTrue(result); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Shared/Channel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Shared 8 | { 9 | public class Channel 10 | { 11 | #region Fields and Properties 12 | 13 | public string ChannelName { get; private set; } 14 | 15 | public bool Following { get; private set; } 16 | 17 | public string ImageUrl { get; set; } 18 | 19 | public int Followers { get; set; } 20 | 21 | public bool Sponsored { get; set; } 22 | 23 | public bool Unread { get; set; } 24 | 25 | #endregion 26 | 27 | #region Constructor 28 | 29 | 30 | public Channel(string channelName, bool following = false) 31 | { 32 | ChannelName = channelName; 33 | Following = following; 34 | } 35 | 36 | #endregion 37 | 38 | #region Methods 39 | 40 | internal Channel UpdateProperties(string imageUrl, int followers) 41 | { 42 | ImageUrl = imageUrl; 43 | Followers = followers; 44 | return this; 45 | } 46 | internal Channel UpdateProperties(int followers, bool sponsored, bool unread) 47 | { 48 | Unread = unread; 49 | Followers = followers; 50 | Sponsored = sponsored; 51 | return this; 52 | } 53 | 54 | #endregion 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JodelAPI", "JodelAPI\JodelAPI.csproj", "{2FE543A6-F341-49D3-9CFD-98559341C69C}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JodelAPITests", "JodelAPITests\JodelAPITests.csproj", "{F10ED5B5-3F17-44F0-950F-2F323D9B0A48}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2FE543A6-F341-49D3-9CFD-98559341C69C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {2FE543A6-F341-49D3-9CFD-98559341C69C}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {2FE543A6-F341-49D3-9CFD-98559341C69C}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {2FE543A6-F341-49D3-9CFD-98559341C69C}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {F10ED5B5-3F17-44F0-950F-2F323D9B0A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {F10ED5B5-3F17-44F0-950F-2F323D9B0A48}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {F10ED5B5-3F17-44F0-950F-2F323D9B0A48}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {F10ED5B5-3F17-44F0-950F-2F323D9B0A48}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPITests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("JodelAPITests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("JodelAPITests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f10ed5b5-3f17-44f0-950f-2f323d9b0a48")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Request/JsonRequestPostJodel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Json.Request 8 | { 9 | internal class JsonRequestPostJodel : JsonRequest 10 | { 11 | #region Fields and Properties 12 | 13 | public string ancestor { get; set; } = null; 14 | public string color { get; set; } 15 | public Location location { get; set; } = new Location(); 16 | public string message { get; set; } 17 | public bool to_home { get; set; } 18 | public string image { get; set; } 19 | 20 | #endregion 21 | 22 | #region Methods 23 | 24 | public bool ShouldSerializeImage() 25 | { 26 | return image != null; 27 | } 28 | 29 | #endregion 30 | 31 | #region Internal Classes 32 | 33 | internal class Location 34 | { 35 | #region Fields and Properties 36 | 37 | public string city { get; set; } 38 | public string country { get; set; } 39 | public double loc_accuracy { get; set; } = 0.0; 40 | public Position loc_coordinates { get; set; } = new Position(); 41 | public string name { get; set; } 42 | 43 | #endregion 44 | } 45 | 46 | internal class Position 47 | { 48 | #region Fields and Properties 49 | 50 | public double lat { get; set; } 51 | public double lng { get; set; } 52 | 53 | #endregion 54 | } 55 | 56 | #endregion 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Allgemeine Informationen über eine Assembly werden über die folgenden 6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 7 | // die einer Assembly zugeordnet sind. 8 | [assembly: AssemblyTitle("JodelAPI")] 9 | [assembly: AssemblyDescription("A .NET wrapper for the Jodel API")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Luca Marcelli")] 12 | [assembly: AssemblyProduct("JodelAPI")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 19 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. 20 | [assembly: ComVisible(false)] 21 | 22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 23 | [assembly: Guid("2fe543a6-f341-49d3-9cfd-98559341c69c")] 24 | 25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 26 | // 27 | // Hauptversion 28 | // Nebenversion 29 | // Buildnummer 30 | // Revision 31 | // 32 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 33 | // übernehmen, indem Sie "*" eingeben: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("4.42.4")] 36 | [assembly: AssemblyFileVersion("4.42.4")] 37 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonMyPins.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonMyPins 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | } 18 | 19 | public class Post 20 | { 21 | public string post_id { get; set; } 22 | public string created_at { get; set; } 23 | public string message { get; set; } 24 | public int discovered_by { get; set; } 25 | public string updated_at { get; set; } 26 | public string post_own { get; set; } 27 | public int discovered { get; set; } 28 | public string voted { get; set; } 29 | public bool pinned { get; set; } 30 | public int pin_count { get; set; } 31 | public int distance { get; set; } 32 | public int child_count { get; set; } 33 | public List children { get; set; } 34 | public int vote_count { get; set; } 35 | public string color { get; set; } 36 | public Location location { get; set; } 37 | public List tags { get; set; } 38 | public string user_handle { get; set; } 39 | } 40 | 41 | public class RootObject 42 | { 43 | public List posts { get; set; } 44 | public int max { get; set; } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonMyJodels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonMyJodels 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | } 18 | 19 | public class Post 20 | { 21 | public string post_id { get; set; } 22 | public string created_at { get; set; } 23 | public string message { get; set; } 24 | public int discovered_by { get; set; } 25 | public string updated_at { get; set; } 26 | public string post_own { get; set; } 27 | public int discovered { get; set; } 28 | public string voted { get; set; } 29 | public int distance { get; set; } 30 | public int pin_count { get; set; } 31 | public int child_count { get; set; } 32 | public List children { get; set; } 33 | public int vote_count { get; set; } 34 | public string color { get; set; } 35 | public bool notifications_enabled { get; set; } 36 | public Location location { get; set; } 37 | public List tags { get; set; } 38 | public string user_handle { get; set; } 39 | } 40 | 41 | public class RootObject 42 | { 43 | public List posts { get; set; } 44 | public int max { get; set; } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonJodelsLastRound.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonJodelsLastRound 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | } 18 | 19 | public class Post 20 | { 21 | public string post_id { get; set; } 22 | public string created_at { get; set; } 23 | public string message { get; set; } 24 | public int discovered_by { get; set; } 25 | public string updated_at { get; set; } 26 | public string post_own { get; set; } 27 | public int discovered { get; set; } 28 | public int distance { get; set; } 29 | public int pin_count { get; set; } 30 | public int vote_count { get; set; } 31 | public string color { get; set; } 32 | public bool notifications_enabled { get; set; } 33 | public Location location { get; set; } 34 | public List ptp_location { get; set; } 35 | public List tags { get; set; } 36 | public string user_handle { get; set; } 37 | public int? child_count { get; set; } 38 | public List children { get; set; } 39 | public string image_url { get; set; } 40 | } 41 | 42 | public class RootObject 43 | { 44 | public List posts { get; set; } 45 | public int max { get; set; } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonGCoordinates.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonGCoordinates 6 | { 7 | public class AddressComponent 8 | { 9 | public string long_name { get; set; } 10 | public string short_name { get; set; } 11 | public List types { get; set; } 12 | } 13 | 14 | public class Location 15 | { 16 | public double lat { get; set; } 17 | public double lng { get; set; } 18 | } 19 | 20 | public class Northeast 21 | { 22 | public double lat { get; set; } 23 | public double lng { get; set; } 24 | } 25 | 26 | public class Southwest 27 | { 28 | public double lat { get; set; } 29 | public double lng { get; set; } 30 | } 31 | 32 | public class Viewport 33 | { 34 | public Northeast northeast { get; set; } 35 | public Southwest southwest { get; set; } 36 | } 37 | 38 | public class Geometry 39 | { 40 | public Location location { get; set; } 41 | public string location_type { get; set; } 42 | public Viewport viewport { get; set; } 43 | } 44 | 45 | public class Result 46 | { 47 | public List address_components { get; set; } 48 | public string formatted_address { get; set; } 49 | public Geometry geometry { get; set; } 50 | public string place_id { get; set; } 51 | public List types { get; set; } 52 | } 53 | 54 | public class RootObject 55 | { 56 | public List results { get; set; } 57 | public string status { get; set; } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonMyVotes.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonMyVotes 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | } 18 | 19 | public class ImageHeaders 20 | { 21 | public string Host { get; set; } 22 | public string Authorization { get; set; } 23 | } 24 | 25 | public class Post 26 | { 27 | public string post_id { get; set; } 28 | public string created_at { get; set; } 29 | public string message { get; set; } 30 | public int discovered_by { get; set; } 31 | public string updated_at { get; set; } 32 | public string post_own { get; set; } 33 | public int discovered { get; set; } 34 | public string voted { get; set; } 35 | public int distance { get; set; } 36 | public int vote_count { get; set; } 37 | public string color { get; set; } 38 | public Location location { get; set; } 39 | public List tags { get; set; } 40 | public string user_handle { get; set; } 41 | public int? child_count { get; set; } 42 | public List children { get; set; } 43 | public string image_url { get; set; } 44 | public ImageHeaders image_headers { get; set; } 45 | public string thumbnail_url { get; set; } 46 | } 47 | 48 | public class RootObject 49 | { 50 | public List posts { get; set; } 51 | public int max { get; set; } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonMyComments.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonMyComments 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | } 18 | 19 | public class ImageHeaders 20 | { 21 | public string Host { get; set; } 22 | public string Authorization { get; set; } 23 | } 24 | 25 | public class Post 26 | { 27 | public string post_id { get; set; } 28 | public string created_at { get; set; } 29 | public string message { get; set; } 30 | public int discovered_by { get; set; } 31 | public string updated_at { get; set; } 32 | public string post_own { get; set; } 33 | public int discovered { get; set; } 34 | public string voted { get; set; } 35 | public int distance { get; set; } 36 | public int child_count { get; set; } 37 | public List children { get; set; } 38 | public int vote_count { get; set; } 39 | public string color { get; set; } 40 | public Location location { get; set; } 41 | public List tags { get; set; } 42 | public string user_handle { get; set; } 43 | public string image_url { get; set; } 44 | public ImageHeaders image_headers { get; set; } 45 | public string thumbnail_url { get; set; } 46 | } 47 | 48 | public class RootObject 49 | { 50 | public List posts { get; set; } 51 | public int max { get; set; } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Shared/Location.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Web; 9 | using JodelAPI.Json.Response; 10 | using Newtonsoft.Json; 11 | 12 | namespace JodelAPI.Shared 13 | { 14 | public class Location 15 | { 16 | #region Fields and Properties 17 | 18 | public string Place { get; private set; } 19 | 20 | public double Longitude { get; private set; } 21 | 22 | public double Latitude { get; private set; } 23 | 24 | #endregion 25 | 26 | #region Constructor 27 | 28 | internal Location(string place) 29 | { 30 | SetNewPlace(place); 31 | } 32 | 33 | #endregion 34 | 35 | #region Methods 36 | 37 | public void SetNewPlace(string place) 38 | { 39 | Place = place; 40 | FindCoordinates(); 41 | } 42 | 43 | public void SetNewPlace(double lat, double lng) 44 | { 45 | Latitude = lat; 46 | Longitude = lng; 47 | } 48 | 49 | void FindCoordinates() 50 | { 51 | string api = "https://maps.googleapis.com/maps/api/geocode/json?address=" + HttpUtility.UrlEncode(Place); 52 | 53 | WebClient client = new WebClient 54 | { 55 | Encoding = Encoding.UTF8 56 | }; 57 | 58 | string stringJson = client.DownloadString(api); 59 | 60 | var gCoords = JsonConvert.DeserializeObject(stringJson); 61 | 62 | if (gCoords.status == "ZERO_RESULTS") 63 | { 64 | throw new LocationNotFoundException($"Location '{Place}' has not been found."); 65 | } 66 | 67 | Latitude = gCoords.results[0].geometry.location.lat; 68 | Longitude = gCoords.results[0].geometry.location.lng; 69 | } 70 | 71 | #endregion 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/JodelApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using JodelAPI.Shared; 7 | 8 | namespace JodelAPI 9 | { 10 | /// 11 | /// Simulates real use of the JodelApp on Android 12 | /// 13 | public class JodelApp 14 | { 15 | #region Fields and Properties 16 | 17 | public int Karma { get; private set; } 18 | public Jodel MyJodel { get; private set; } 19 | public JodelMainData JodelPosts { get; set; } 20 | 21 | #endregion 22 | 23 | #region Constructor 24 | 25 | public JodelApp(Jodel jodel) 26 | { 27 | Karma = 0; 28 | MyJodel = jodel; 29 | } 30 | 31 | #endregion 32 | 33 | #region Methods 34 | 35 | public void Start() 36 | { 37 | MyJodel.GetUserConfig(); 38 | MyJodel.GetRecommendedChannels(); 39 | Karma = MyJodel.GetKarma(); 40 | JodelPosts = MyJodel.GetPostLocationCombo(stickies: true); 41 | } 42 | 43 | 44 | 45 | #region Reload 46 | 47 | public JodelMainData ReloadMain() 48 | { 49 | Karma = MyJodel.GetKarma(); 50 | JodelPosts = MyJodel.GetPostLocationCombo(); 51 | 52 | return JodelPosts; 53 | } 54 | 55 | /// 56 | /// Loads more Jodels 57 | /// 58 | /// 59 | /// The loaded Posts 60 | public IEnumerable LoadMoreRecentPosts(string postId = "") 61 | { 62 | List posts = MyJodel.GetRecentPostsAfter(string.IsNullOrWhiteSpace(postId) ? JodelPosts.RecentJodels.Last().PostId : postId).ToList(); 63 | JodelPosts.RecentJodels.AddRange(posts); 64 | return posts; 65 | } 66 | 67 | #endregion 68 | 69 | #region Posts 70 | 71 | 72 | 73 | #endregion 74 | 75 | #endregion 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Internal/JodelWebClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace JodelAPI.Internal 11 | { 12 | [System.ComponentModel.DesignerCategory("Code")] 13 | internal class JodelWebClient : WebClient 14 | { 15 | protected override WebRequest GetWebRequest(Uri address) 16 | { 17 | HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest; 18 | request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; 19 | request.ServicePoint.Expect100Continue = false; 20 | return request; 21 | } 22 | 23 | internal static JodelWebClient GetJodelWebClientWithHeaders(DateTime time, string stringifiedPayload, string accesstoken = "", bool addBearer = false, HttpMethod method = null) 24 | { 25 | JodelWebClient client = new JodelWebClient(); 26 | 27 | var headers = Constants.Header; 28 | 29 | headers.Remove("X-Authorization"); 30 | headers.Remove("X-Timestamp"); 31 | headers.Remove("Authorization"); 32 | 33 | var keyByte = Encoding.UTF8.GetBytes(Constants.Key); 34 | var hmacsha1 = new HMACSHA1(keyByte); 35 | hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(stringifiedPayload)); 36 | 37 | headers.Add("X-Timestamp", $"{time:s}Z"); 38 | headers.Add("X-Authorization", "HMAC " + hmacsha1.Hash.Aggregate(string.Empty, (current, t) => current + t.ToString("X2"))); 39 | 40 | if (addBearer) 41 | { 42 | headers.Add("Authorization", "Bearer " + accesstoken); 43 | } 44 | 45 | client.Headers.Add(headers); 46 | 47 | if (method != HttpMethod.Get) 48 | client.Headers.Add(Constants.JsonHeader); 49 | 50 | client.Encoding = Encoding.UTF8; 51 | 52 | return client; 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonPostJodels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonPostJodels 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | public string city { get; set; } 18 | public string country { get; set; } 19 | public int loc_accuracy { get; set; } 20 | } 21 | 22 | public class ImageHeaders 23 | { 24 | public string Host { get; set; } 25 | public string Authorization { get; set; } 26 | } 27 | 28 | public class Post 29 | { 30 | public string post_id { get; set; } 31 | public string created_at { get; set; } 32 | public string message { get; set; } 33 | public int discovered_by { get; set; } 34 | public string updated_at { get; set; } 35 | public string post_own { get; set; } 36 | public int discovered { get; set; } 37 | public int distance { get; set; } 38 | public int vote_count { get; set; } 39 | public string color { get; set; } 40 | public Location location { get; set; } 41 | public List tags { get; set; } 42 | public string user_handle { get; set; } 43 | public string image_url { get; set; } 44 | public ImageHeaders image_headers { get; set; } 45 | public string thumbnail_url { get; set; } 46 | public string voted { get; set; } 47 | public int? child_count { get; set; } 48 | public List children { get; set; } 49 | public bool got_thanks { get; set; } 50 | public bool notifications_enabled { get; set; } 51 | public int pin_count { get; set; } 52 | } 53 | 54 | public class RootObject 55 | { 56 | public List posts { get; set; } 57 | public int max { get; set; } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Shared/AccessToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Runtime.CompilerServices; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using JodelAPI.Internal; 10 | using JodelAPI.Json; 11 | using JodelAPI.Json.Request; 12 | using JodelAPI.Json.Response; 13 | using Newtonsoft.Json; 14 | 15 | namespace JodelAPI.Shared 16 | { 17 | public class AccessToken 18 | { 19 | #region Fields and Properties 20 | 21 | public string DeviceUid { get; set; } 22 | 23 | public string Token { get; set; } 24 | 25 | public string RefreshToken { get; set; } 26 | 27 | public int ExpirationDate { get; set; } 28 | 29 | /// 30 | /// UTC-ExpirationDate 31 | /// 32 | public DateTime ExpirationDateTime 33 | { 34 | get 35 | { 36 | DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 37 | dateTime = dateTime.AddSeconds(ExpirationDate); 38 | return dateTime; 39 | } 40 | } 41 | 42 | public string DistinctId { get; set; } 43 | 44 | public string TokenType { get; set; } 45 | 46 | public User UserConfig { get; set; } 47 | 48 | #endregion 49 | 50 | #region Constructor 51 | 52 | public AccessToken(User user) 53 | { 54 | DeviceUid = string.Empty; 55 | UserConfig = user; 56 | } 57 | 58 | public AccessToken(User user, string deviceUid, string token) 59 | : this(user) 60 | { 61 | DeviceUid = deviceUid; 62 | Token = token; 63 | } 64 | 65 | public AccessToken(User user, string deviceUid, string token, int expirationDate, string distinctId, string tokenType, string refreshToken) 66 | : this(user, deviceUid, token) 67 | { 68 | ExpirationDate = expirationDate; 69 | DistinctId = distinctId; 70 | TokenType = tokenType; 71 | RefreshToken = refreshToken; 72 | } 73 | 74 | #endregion 75 | 76 | #region Methods 77 | 78 | #endregion 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Shared/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.CompilerServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace JodelAPI.Shared 9 | { 10 | public class User 11 | { 12 | #region Fields and Properties 13 | 14 | 15 | public Location Place { get; set; } 16 | public string CountryCode { get; set; } 17 | public string CityName { get; set; } 18 | public AccessToken Token { get; set; } 19 | 20 | #region UserProperties 21 | 22 | public bool Moderator { get; set; } 23 | public object UserType { get; set; } 24 | public List Experiments { get; set; } = new List(); 25 | public List FollowedChannels { get; set; } = new List(); 26 | public List FollowedHashtags { get; set; } = new List(); 27 | public int ChannelsFollowLimit { get; set; } 28 | public bool TripleFeedEnabled { get; set; } 29 | public string HomeName { get; set; } 30 | public bool HomeSet { get; set; } 31 | public string Location { get; set; } 32 | public bool Verified { get; set; } 33 | 34 | #endregion 35 | 36 | #endregion 37 | 38 | #region Constructor 39 | 40 | public User() 41 | { 42 | Token = new AccessToken(this); 43 | } 44 | 45 | public User(string deviceUid, string accessToken) 46 | { 47 | Token = new AccessToken(this, deviceUid, accessToken); 48 | } 49 | 50 | public User(AccessToken token) 51 | { 52 | Token = token; 53 | } 54 | 55 | #endregion 56 | 57 | #region UserClasses 58 | 59 | public class Experiment 60 | { 61 | #region Fields and Properties 62 | 63 | public string Name { get; private set; } 64 | public string Group { get; private set; } 65 | public List Features { get; private set; } 66 | 67 | #endregion 68 | 69 | #region Constructor 70 | 71 | internal Experiment(string name, string group, List features) 72 | { 73 | Name = name; 74 | Group = group; 75 | Features = features; 76 | } 77 | 78 | #endregion 79 | } 80 | 81 | #endregion 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonComments.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonComments 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | } 18 | 19 | public class Child 20 | { 21 | public string post_id { get; set; } 22 | public string created_at { get; set; } 23 | public string message { get; set; } 24 | public int discovered_by { get; set; } 25 | public string updated_at { get; set; } 26 | public string post_own { get; set; } 27 | public int discovered { get; set; } 28 | public int distance { get; set; } 29 | public int parent_creator { get; set; } 30 | public int vote_count { get; set; } 31 | public string color { get; set; } 32 | public Location location { get; set; } 33 | public string user_handle { get; set; } 34 | public string image_url { get; set; } 35 | } 36 | 37 | public class LocCoordinates2 38 | { 39 | public int lat { get; set; } 40 | public int lng { get; set; } 41 | } 42 | 43 | public class Location2 44 | { 45 | public string name { get; set; } 46 | public LocCoordinates2 loc_coordinates { get; set; } 47 | } 48 | 49 | public class RootObject 50 | { 51 | public string post_id { get; set; } 52 | public string created_at { get; set; } 53 | public string message { get; set; } 54 | public int discovered_by { get; set; } 55 | public string updated_at { get; set; } 56 | public string post_own { get; set; } 57 | public int discovered { get; set; } 58 | public string voted { get; set; } 59 | public int distance { get; set; } 60 | public int child_count { get; set; } 61 | public List children { get; set; } 62 | public int vote_count { get; set; } 63 | public string color { get; set; } 64 | public Location2 location { get; set; } 65 | public List tags { get; set; } 66 | public string user_handle { get; set; } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Shared/Captcha.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JodelAPI.Shared 8 | { 9 | public class Captcha 10 | { 11 | public Captcha(byte[] image, string key, string imageUrl) 12 | { 13 | Image = image; 14 | Key = key; 15 | ImageUrl = imageUrl; 16 | } 17 | 18 | public Captcha(byte[] image, string key, string imageUrl, int imageSize) 19 | : this(image, key, imageUrl) 20 | { 21 | ImageSize = imageSize; 22 | } 23 | 24 | public byte[] Image { get; } 25 | public string Key { get; } 26 | public string ImageUrl { get; } 27 | public int ImageSize { get; } 28 | 29 | // Example extracted from OJOC. This array can be used for autosolving the captcha. Fill it with your values. it's MD5 & int[] with the answer 30 | public static Dictionary Solutions = new Dictionary() 31 | { 32 | {"4d97884c3806a531ddb7288bf0eab418", new[]{1,3,5}}, 33 | {"08116dcafc684462ea1948819475a81c", new[]{7,8}}, 34 | {"389aa660266f0a8f76b5ef21c60cf6fd", new[]{1,2}}, 35 | {"42c904d3cd20f55405a64fcf8032b92a", new[]{2,6,8}}, 36 | {"2a819973e9e6e22eeb445f548201ab40", new[]{0,5}}, 37 | {"4d9a9b459f0d3c67581c4990bda3257a", new[]{0,2,3}}, 38 | {"2be5ec6995af4925299ed2fa635e4782", new[]{1,5,7}}, 39 | {"61e0c2f52d510cc89b7432da01494a68", new[]{0,4}}, 40 | {"2ea52cb78ba770b72149daa428331e98", new[]{4}}, 41 | {"55bd1a0cc31c4d57654d927ca05b81a4", new[]{2,4,5}}, 42 | {"681f0615747ba54f97040ef36dd2e6a0", new[]{1}}, 43 | {"4fed27abf3b4fa6dad5cf1d852114a1e", new[]{2,7}}, 44 | {"549f069a0189e73f43640a10f7be0de2", new[]{5,6,8}}, 45 | {"d09f368da26b9ed9d583d61f0dd4b1dd", new[]{3}}, 46 | {"2224eef78d48f63536bc7e0730ebfd54", new[]{1,6,7}}, 47 | {"5055db4cab5e09eeeac0293ca44ebf65", new[]{1,2,7}}, 48 | {"76a3a9ced6474f3db148568d2f396dd6", new[]{1,5,8}}, 49 | {"50abf6c375ea3115168da3be0acc5485", new[]{5}}, 50 | {"9329c0fecaece67da26a740d3519970b", new[]{0,1,8}}, 51 | {"b04955d8598980df71c7b69ea3a8e7a2", new[]{2,7,8}}, 52 | {"2ba5296ea4cb4bcd302f5a3b624ecf82", new[]{1,7,8}}, 53 | {"93af8a552ecf9729493b5c9fea98c748", new[]{3,4,6}}, 54 | {"5b9a9ae117ebe53e71d236ea3952b974", new[]{1,4,6}}, 55 | {"b435d7145639469b151a6b01a0bfe1c6", new[]{2,5,8}}, 56 | {"0635a32edc11e674f48dbbfbae98c969", new[]{3,7,8}}, 57 | {"18eaa52fcf87e47edd684c8696aa1798", new[]{0,4,6}}, 58 | {"49a857ed6a90225b7de5b9ed22ee2c8a", new[]{3,4}}, 59 | {"3f86e8960a64f884aa45ecb696890f5c", new[]{0,1,8}}, 60 | {"e785f87dec2b23818dbb8892ea48f91d", new[]{4,5}} 61 | }; 62 | } 63 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JodelAPI (Not working on this anymore) 2 | [![forthebadge](http://forthebadge.com/images/badges/built-with-swag.svg)](http://forthebadge.com) 3 | [![forthebadge](http://forthebadge.com/images/badges/gluten-free.svg)](http://forthebadge.com) 4 | [![forthebadge](http://forthebadge.com/images/badges/certified-snoop-lion.svg)](http://forthebadge.com) 5 | 6 | *Big thanks to KirschbaumP* 7 | 8 | [![Build status](https://ci.appveyor.com/api/projects/status/2dx3f591ubmp978t?svg=true)](https://ci.appveyor.com/project/ioncodes/jodelapi) 9 | [![Github All Releases](https://img.shields.io/github/downloads/ioncodes/JodelAPI/total.svg)](https://github.com/ioncodes/JodelAPI/releases) 10 | [![NuGet](https://img.shields.io/nuget/v/JodelAPI.svg)](https://www.nuget.org/packages/JodelAPI/) 11 | [![Status](https://img.shields.io/badge/api-working-brightgreen.svg)]() 12 | [![Implementation](https://img.shields.io/badge/api--version-4.47.0-brightgreen.svg)]() 13 | [![Test status](http://teststatusbadge.azurewebsites.net/api/status/ioncodes/jodelapi)](https://ci.appveyor.com/project/ioncodes/jodelapi) 14 | [![Gitter chat](https://badges.gitter.im/ioncodes/JodelAPI.svg)](https://gitter.im/JodelAPI/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link) 15 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JTJ7KE332VBE) 16 | 17 | ## READ THIS FIRST 18 | 19 | I received a message from the Jodel Team, and they would like me to close this repo. We are currently in a discussion with them, if it's possible to let this repo open for educational purposes. 20 | **However, I'm not allowed to work on this library until I receive their permission** 21 | **All GET requests are ok to use.** 22 | 23 | ## INFO 24 | 25 | * Jodel dropped the captcha support, which means you wont be able to verify new accounts. If you have verified accounts, they will continue to work on 4.47.0, but if you use the 4.48.0 version, they will get unverified again, so use the 4.48.0 branch with caution! 26 | 27 | ## Support 28 | 29 | You can show me your love by paying me a coffee :) You can find the PayPal page at the badge bar. 30 | 31 | ## Introduction 32 | 33 | This is the carefully reverse-engineered .NET Jodel API in C#. Please feel free to grab the source or compiled library from the link provided below. 34 | 35 | *This is a Swiss software product and therefore might be awesome!* 36 | 37 | ## Binaries and pre-requisites 38 | * [GitHub Releases](https://github.com/ioncodes/JodelAPI/releases) or from Nuget 39 | 40 | ## Let's get right into it! 41 | Create a Jodel object which holds all functions needed: 42 | ```cs 43 | Jodel jodel = new Jodel(string place, string countrycode, string city, bool createToken = false); // YOU HAVE TO SET YOUR OWN TOKEN 44 | ``` 45 | Where 'place' is the place how you would enter the location in Google Maps, 'countrycode' and 'city' are the values that are sent to Jodel! You might have your own token, in that case you can set createToken to false (You have to). If you do this, make sure to set the data found in the AccessToken (Account.AccessToken) class: 46 | ```cs 47 | jodel.Account.Token.Token = ""; 48 | jodel.Account.Token.RefreshToken = ""; 49 | ``` 50 | 51 | Your data is stored in the 'Account' field, which comes from the 'User' class. You can defined a 'User' object yourself and pass it to the Jodel constructor. This gives you extra options, such as setting the 'Location' object yourself (Latitude, Longitude), etc: 52 | ```cs 53 | User user = new User(); 54 | user.Location.Longitude = 13.37; 55 | // ... 56 | Jodel jodel = new Jodel(user); 57 | ``` 58 | 59 | After creating your 'Jodel' object, you will find all methods you need in there. 60 | 61 | A plain list of all supported endpoints can be found [here](https://github.com/ioncodes/JodelAPI/blob/master/JodelAPI/JodelAPI/Internal/Links.cs) 62 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Internal/Links.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using JodelAPI.Shared; 9 | 10 | namespace JodelAPI.Internal 11 | { 12 | internal static class Links 13 | { 14 | #region ApiCalls 15 | 16 | // Base URL 17 | public const string ApiBaseUrl = "api.go-tellm.com"; 18 | 19 | #region User 20 | 21 | public static readonly ApiCall GetKarma = new ApiCall(HttpMethod.Get, "/users/karma", "v2"); 22 | public static readonly ApiCall GetUserConfig = new ApiCall(HttpMethod.Get, "/user/config"); 23 | public static readonly ApiCall GetMyPosts = new ApiCall(HttpMethod.Get, "/posts/mine/", "v2"); 24 | public static readonly ApiCall GetMyRepliedPosts = new ApiCall(HttpMethod.Get, "/posts/mine/replies/", "v2"); 25 | public static readonly ApiCall GetMyVotedPosts = new ApiCall(HttpMethod.Get, "/posts/mine/votes/", "v2"); 26 | public static readonly ApiCall GetMyPostsCombo = new ApiCall(HttpMethod.Get, "/posts/mine/combo/", "v2"); 27 | public static readonly ApiCall GetMyPopularPosts = new ApiCall(HttpMethod.Get, "/posts/mine/popular/", "v2"); 28 | public static readonly ApiCall GetMyMostDiscussedPosts = new ApiCall(HttpMethod.Get, "/posts/mine/discussed/", "v2"); 29 | public static readonly ApiCall GetMyPinnedPosts = new ApiCall(HttpMethod.Get, "/posts/mine/pinned/", "v2"); 30 | 31 | #endregion 32 | 33 | #region Posts 34 | 35 | public static readonly ApiCall GetMostRecentPosts = new ApiCall(HttpMethod.Get, "/posts/location/", "v2"); 36 | public static readonly ApiCall GetPostsCombo = new ApiCall(HttpMethod.Get, "/posts/location/combo"); 37 | public static readonly ApiCall GetMostPopularPosts = new ApiCall(HttpMethod.Get, "/posts/location/popular/", "v2"); 38 | public static readonly ApiCall GetMostDiscussedPosts = new ApiCall(HttpMethod.Get, "/posts/location/discussed/", "v2"); 39 | public static readonly ApiCall GetPost = new ApiCall(HttpMethod.Get, "/posts/", "v2"); 40 | public static readonly ApiCall GetPostDetails = new ApiCall(HttpMethod.Get, "/posts/", postAction: "/details"); 41 | 42 | #endregion 43 | 44 | #region Channels 45 | 46 | public static readonly ApiCall GetChannelCombo = new ApiCall(HttpMethod.Get, "/posts/channel/combo/"); 47 | public static readonly ApiCall GetPopularChannelPosts = new ApiCall(HttpMethod.Get, "/posts/channel/popular"); 48 | public static readonly ApiCall GetDiscussedChannelPosts = new ApiCall(HttpMethod.Get, "/posts/channel/discussed"); 49 | public static readonly ApiCall GetRecentChannelPosts = new ApiCall(HttpMethod.Get, "/posts/channel"); 50 | public static readonly ApiCall GetRecommendedChannels = new ApiCall(HttpMethod.Get, "/user/recommendedChannels"); 51 | public static readonly ApiCall GetChannelMeta = new ApiCall(HttpMethod.Get, "/user/channelMeta"); 52 | 53 | #endregion 54 | 55 | #region Hashtags 56 | 57 | public static readonly ApiCall GetDiscussedHashtagPosts = new ApiCall(HttpMethod.Get, "/posts/hashtag/discussed"); 58 | public static readonly ApiCall GetPopularHashtagPosts = new ApiCall(HttpMethod.Get, "/posts/hashtag/popular"); 59 | public static readonly ApiCall GetHashtagCombo = new ApiCall(HttpMethod.Get, "/posts/hashtag/combo"); 60 | public static readonly ApiCall GetRecentHashtagPosts = new ApiCall(HttpMethod.Get, "/posts/hashtag"); 61 | 62 | #endregion 63 | 64 | #region Moderation 65 | 66 | public static readonly ApiCall GetModerationFeed = new ApiCall(HttpMethod.Get, "/moderation"); 67 | 68 | #endregion 69 | 70 | #region Misc 71 | 72 | #endregion 73 | 74 | #endregion 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Json/Response/JsonGetJodelsFromChannel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace JodelAPI.Json.Response 4 | { 5 | internal class JsonGetJodelsFromChannel 6 | { 7 | public class LocCoordinates 8 | { 9 | public int lat { get; set; } 10 | public int lng { get; set; } 11 | } 12 | 13 | public class Location 14 | { 15 | public string name { get; set; } 16 | public LocCoordinates loc_coordinates { get; set; } 17 | } 18 | 19 | public class Recent 20 | { 21 | public string post_id { get; set; } 22 | public string created_at { get; set; } 23 | public string message { get; set; } 24 | public int discovered_by { get; set; } 25 | public string updated_at { get; set; } 26 | public string post_own { get; set; } 27 | public int discovered { get; set; } 28 | public int pin_count { get; set; } 29 | public int distance { get; set; } 30 | public int child_count { get; set; } 31 | public List children { get; set; } 32 | public int vote_count { get; set; } 33 | public string color { get; set; } 34 | public Location location { get; set; } 35 | public List tags { get; set; } 36 | public string user_handle { get; set; } 37 | } 38 | 39 | public class LocCoordinates2 40 | { 41 | public int lat { get; set; } 42 | public int lng { get; set; } 43 | } 44 | 45 | public class Location2 46 | { 47 | public string name { get; set; } 48 | public LocCoordinates2 loc_coordinates { get; set; } 49 | } 50 | 51 | public class Replied 52 | { 53 | public string post_id { get; set; } 54 | public string created_at { get; set; } 55 | public string message { get; set; } 56 | public int discovered_by { get; set; } 57 | public string updated_at { get; set; } 58 | public string post_own { get; set; } 59 | public int discovered { get; set; } 60 | public int distance { get; set; } 61 | public int child_count { get; set; } 62 | public List children { get; set; } 63 | public int vote_count { get; set; } 64 | public string color { get; set; } 65 | public Location2 location { get; set; } 66 | public List tags { get; set; } 67 | public string user_handle { get; set; } 68 | public int? pin_count { get; set; } 69 | } 70 | 71 | public class LocCoordinates3 72 | { 73 | public int lat { get; set; } 74 | public int lng { get; set; } 75 | } 76 | 77 | public class Location3 78 | { 79 | public string name { get; set; } 80 | public LocCoordinates3 loc_coordinates { get; set; } 81 | } 82 | 83 | public class Voted 84 | { 85 | public string post_id { get; set; } 86 | public string created_at { get; set; } 87 | public string message { get; set; } 88 | public int discovered_by { get; set; } 89 | public string updated_at { get; set; } 90 | public string post_own { get; set; } 91 | public int discovered { get; set; } 92 | public int pin_count { get; set; } 93 | public int distance { get; set; } 94 | public int child_count { get; set; } 95 | public List children { get; set; } 96 | public int vote_count { get; set; } 97 | public string color { get; set; } 98 | public Location3 location { get; set; } 99 | public List tags { get; set; } 100 | public string user_handle { get; set; } 101 | } 102 | 103 | public class RootObject 104 | { 105 | public List recent { get; set; } 106 | public List replied { get; set; } 107 | public List voted { get; set; } 108 | public int max { get; set; } 109 | public int followers_count { get; set; } 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /JodelAPI/JodelAPITests/JodelAPITests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {F10ED5B5-3F17-44F0-950F-2F323D9B0A48} 7 | Library 8 | Properties 9 | JodelAPITests 10 | JodelAPITests 11 | v4.6.1 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {2FE543A6-F341-49D3-9CFD-98559341C69C} 60 | JodelAPI 61 | 62 | 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | False 71 | 72 | 73 | False 74 | 75 | 76 | False 77 | 78 | 79 | 80 | 81 | 82 | 83 | 90 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Internal/ApiCall.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Runtime.CompilerServices; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using JodelAPI.Json.Request; 10 | using JodelAPI.Json.Response; 11 | using JodelAPI.Shared; 12 | using Newtonsoft.Json; 13 | using Newtonsoft.Json.Linq; 14 | 15 | namespace JodelAPI.Internal 16 | { 17 | internal class ApiCall 18 | { 19 | public HttpMethod Method { get; } 20 | 21 | public string Url { get; } 22 | 23 | public string Version { get; } 24 | 25 | public string Action { get; } 26 | 27 | public bool Authorize { get; } 28 | 29 | /// 30 | /// API Call 31 | /// 32 | /// HTTP Method 33 | /// URL to be appended to base url 34 | /// API version to be used 35 | /// Action to be applied to post 36 | /// true if authorization bearer needs to be added to request header, otherwise false 37 | internal ApiCall(HttpMethod method, string url, string version = "v3", string postAction = "", bool authorize = true) 38 | { 39 | Method = method; 40 | Url = url; 41 | Version = version; 42 | Action = postAction; 43 | Authorize = authorize; 44 | } 45 | 46 | internal string ExecuteRequest(User user, Dictionary parameters = null, JsonRequest payload = null, string postId = null, WebProxy proxy = null) 47 | { 48 | string plainJson = null; 49 | string payloadString = payload != null 50 | ? JsonConvert.SerializeObject(payload, Formatting.None, 51 | new JsonSerializerSettings 52 | { 53 | NullValueHandling = NullValueHandling.Ignore 54 | }) 55 | : null; 56 | DateTime dt = DateTime.Now; 57 | string urlParam = Url; 58 | if (!string.IsNullOrWhiteSpace(postId)) urlParam += postId; 59 | if (!string.IsNullOrWhiteSpace(Action)) urlParam += Action; 60 | urlParam += ParamsToString(parameters); 61 | string stringifiedUrl = "https://" + Links.ApiBaseUrl + "/api/" + Version + urlParam; 62 | 63 | string stringifiedPayload = Method.Method + "%" + Links.ApiBaseUrl + "%443%/api/" + Version + urlParam; 64 | stringifiedPayload += "%" + user.Token.Token; 65 | stringifiedPayload += "%" + $"{dt:s}Z" + "%%" + payloadString; 66 | 67 | using (var client = JodelWebClient.GetJodelWebClientWithHeaders(dt, stringifiedPayload, user.Token.Token, Authorize, Method)) 68 | { 69 | #if DEBUG 70 | Console.WriteLine("****************************************************************"); 71 | Console.WriteLine("{0} {1}", Method, stringifiedUrl); 72 | Console.WriteLine("----------------------------------------------------------------"); 73 | Console.WriteLine("----------------------------------------------------------------"); 74 | for (int i = 0; i < client.Headers.Count; i++) 75 | { 76 | Console.WriteLine("{0,-30}{1}", client.Headers.AllKeys[i], client.Headers.GetValues(i).Aggregate((a, b) => a + ", " + b)); 77 | } 78 | Console.WriteLine("----------------------------------------------------------------"); 79 | Console.WriteLine("----------------------------------------------------------------"); 80 | Console.WriteLine(stringifiedPayload); 81 | Console.WriteLine("----------------------------------------------------------------"); 82 | Console.WriteLine(payloadString); 83 | #endif 84 | if (proxy != null) 85 | client.Proxy = proxy; 86 | if (Method == HttpMethod.Get) 87 | { 88 | plainJson = client.DownloadString(stringifiedUrl); 89 | } 90 | else 91 | { 92 | plainJson = client.UploadString(stringifiedUrl, Method.Method, payloadString ?? string.Empty); 93 | } 94 | #if DEBUG 95 | //Console.WriteLine("----------------------------------------------------------------"); 96 | //Console.WriteLine(plainJson); 97 | Console.WriteLine("****************************************************************"); 98 | #endif 99 | } 100 | 101 | return plainJson; 102 | } 103 | 104 | string ParamsToString(Dictionary parameters) 105 | { 106 | return parameters == null ? string.Empty : "?" + string.Join("&", parameters.Select(p => $"{p.Key}={p.Value}")); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/JodelAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2FE543A6-F341-49D3-9CFD-98559341C69C} 8 | Library 9 | Properties 10 | JodelAPI 11 | JodelAPI 12 | v4.6.1 13 | 512 14 | 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | false 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 104 | 105 | 106 | 113 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Shared/JodelPost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using JodelAPI.Json.Response; 8 | using Newtonsoft.Json; 9 | 10 | namespace JodelAPI.Shared 11 | { 12 | public class JodelPost 13 | { 14 | #region Fields and Properties 15 | 16 | public string PostId { get; set; } 17 | public DateTime CreatedAt { get; set; } 18 | public string Message { get; set; } 19 | public int Discovered { get; set; } 20 | public int DiscoveredBy { get; set; } 21 | public int Distance { get; set; } 22 | public bool GotThanks { get; set; } 23 | public Location Place { get; set; } 24 | public bool NotificationsEnabled { get; set; } 25 | public int PinCounted { get; set; } 26 | public string PostOwn { get; set; } 27 | public DateTime UpdatedAt { get; set; } 28 | public string UserHandle { get; set; } 29 | public int VoteCount { get; set; } 30 | public PostColor Color { get; set; } 31 | public int ColorHex 32 | { 33 | get { return (int)Color; } 34 | set { Color = (PostColor)value; } 35 | } 36 | public int ChildCount { get; set; } 37 | public List Children { get; set; } 38 | public string ImageUrl { get; set; } 39 | public string ImageHost { get; set; } 40 | public string ImageAuthorization { get; set; } 41 | public string ThumbnailUrl { get; set; } 42 | public int? Next { get; set; } = null; 43 | public int Remaining { get; set; } = 0; 44 | public string ShareUrl { get; } 45 | 46 | #endregion 47 | 48 | #region Enum 49 | 50 | public enum UpvoteReason 51 | { 52 | Stub = -1, 53 | Cancel = 1, 54 | Funny = 1, 55 | Interesting = 2, 56 | SoTrue = 3, 57 | SaveJodel = 4, 58 | Other = 5 59 | } 60 | 61 | public enum DownvoteReason 62 | { 63 | Stub = -1, 64 | Cancel = 1, 65 | NotInteresting = 1, 66 | Repost = 2, 67 | NotAllowedOnJodel = 3, 68 | GoogleIt = 4, 69 | Other = 5 70 | } 71 | 72 | #endregion 73 | 74 | #region Constructor 75 | 76 | internal JodelPost() 77 | { 78 | 79 | } 80 | 81 | internal JodelPost(JsonPostJodels.Post jodel) 82 | { 83 | ColorHex = int.Parse(jodel.color, NumberStyles.HexNumber); 84 | ChildCount = jodel.child_count ?? 0; 85 | Children = jodel.children?.Select(c => new JodelPost(c)).ToList(); 86 | CreatedAt = DateTime.ParseExact(jodel.created_at.Replace("Z", string.Empty).Replace("T", " "), "yyyy-MM-dd HH:mm:ss.fff", null); 87 | Discovered = jodel.discovered; 88 | DiscoveredBy = jodel.discovered_by; 89 | Distance = jodel.distance; 90 | GotThanks = jodel.got_thanks; 91 | ImageAuthorization = jodel.image_headers?.Authorization; 92 | ImageUrl = jodel.image_url; 93 | ImageHost = jodel.image_headers?.Host; 94 | Message = jodel.message; 95 | NotificationsEnabled = jodel.notifications_enabled; 96 | PinCounted = jodel.pin_count; 97 | Place = new Location 98 | { 99 | Longitude = jodel.location.loc_coordinates.lng, 100 | Latitude = jodel.location.loc_coordinates.lat, 101 | City = jodel.location.city, 102 | Accuracy = jodel.location.loc_accuracy, 103 | Name = jodel.location.name, 104 | Country = jodel.location.country 105 | }; 106 | PostId = jodel.post_id; 107 | PostOwn = jodel.post_own; 108 | ThumbnailUrl = jodel.thumbnail_url; 109 | UpdatedAt = DateTime.ParseExact(jodel.updated_at.Replace("Z", string.Empty).Replace("T", " "), "yyyy-MM-dd HH:mm:ss.fff", null); 110 | UserHandle = jodel.user_handle; 111 | VoteCount = jodel.vote_count; 112 | ShareUrl = "https://share.jodel.com/post?postId=" + PostId; 113 | } 114 | 115 | internal JodelPost(JsonPostDetail.RootObject jodel) 116 | { 117 | Children = jodel.replies?.Select(c => new JodelPost(c)).ToList(); 118 | Next = !string.IsNullOrWhiteSpace(jodel.next) ? int.Parse(jodel.next) : (int?)null; 119 | Remaining = jodel.remaining; 120 | 121 | if (jodel.details != null) 122 | { 123 | ColorHex = int.Parse(jodel.details.color, NumberStyles.HexNumber); 124 | ChildCount = jodel.details.child_count ?? 0; 125 | CreatedAt = DateTime.ParseExact(jodel.details.created_at.Replace("Z", string.Empty).Replace("T", " "), "yyyy-MM-dd HH:mm:ss.fff", null); 126 | Discovered = jodel.details.discovered; 127 | DiscoveredBy = jodel.details.discovered_by; 128 | Distance = jodel.details.distance; 129 | GotThanks = jodel.details.got_thanks; 130 | ImageAuthorization = jodel.details.image_headers?.Authorization; 131 | ImageUrl = jodel.details.image_url; 132 | ImageHost = jodel.details.image_headers?.Host; 133 | Message = jodel.details.message; 134 | NotificationsEnabled = jodel.details.notifications_enabled; 135 | PinCounted = jodel.details.pin_count; 136 | Place = new Location 137 | { 138 | Longitude = jodel.details.location.loc_coordinates.lng, 139 | Latitude = jodel.details.location.loc_coordinates.lat, 140 | City = jodel.details.location.city, 141 | Accuracy = jodel.details.location.loc_accuracy, 142 | Name = jodel.details.location.name, 143 | Country = jodel.details.location.country 144 | }; 145 | PostId = jodel.details.post_id; 146 | PostOwn = jodel.details.post_own; 147 | ThumbnailUrl = jodel.details.thumbnail_url; 148 | UpdatedAt = DateTime.ParseExact(jodel.details.updated_at.Replace("Z", string.Empty).Replace("T", " "), "yyyy-MM-dd HH:mm:ss.fff", null); 149 | UserHandle = jodel.details.user_handle; 150 | VoteCount = jodel.details.vote_count; 151 | ShareUrl = "https://share.jodel.com/post?postId=" + PostId; 152 | } 153 | } 154 | 155 | #endregion 156 | 157 | #region Methods 158 | 159 | 160 | 161 | #endregion 162 | 163 | #region Classes/Enums 164 | 165 | /// 166 | /// Colors for JodelPost 167 | /// 168 | public enum PostColor 169 | { 170 | Orange = 0xFF9908, 171 | Yellow = 0xFFBA00, 172 | Red = 0xDD5F5F, 173 | Blue = 0x06A3CB, 174 | Bluegreyish = 0x8ABDB0, 175 | Green = 0x9EC41C, 176 | Random 177 | } 178 | 179 | public class Location 180 | { 181 | public string City { get; set; } 182 | public string Country { get; set; } 183 | public double Accuracy { get; set; } 184 | public double Latitude { get; set; } 185 | public double Longitude { get; set; } 186 | public string Name { get; set; } 187 | } 188 | 189 | #endregion 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Jodel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Globalization; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Security.Cryptography; 9 | using System.Text; 10 | using JodelAPI.Internal; 11 | using JodelAPI.Json; 12 | using JodelAPI.Json.Request; 13 | using JodelAPI.Json.Response; 14 | using JodelAPI.Shared; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Linq; 17 | 18 | namespace JodelAPI 19 | { 20 | public class Jodel 21 | { 22 | #region Fields and Properties 23 | 24 | public User Account { get; private set; } 25 | 26 | #endregion 27 | 28 | #region Constructor 29 | 30 | public Jodel(User user) 31 | { 32 | Account = user; 33 | } 34 | 35 | public Jodel(string place, string countryCode, string cityName, bool createToken = true) 36 | : this(new User 37 | { 38 | CountryCode = countryCode, 39 | CityName = cityName, 40 | Place = new Location(place), 41 | }) 42 | { 43 | } 44 | 45 | #endregion 46 | 47 | #region Methods 48 | 49 | #region Account 50 | 51 | public void GetUserConfig() 52 | { 53 | string jsonString = Links.GetUserConfig.ExecuteRequest(Account); 54 | 55 | JsonConfig.RootObject config = JsonConvert.DeserializeObject(jsonString); 56 | 57 | List experiments = new List(config.experiments.Count); 58 | experiments.AddRange(config.experiments.Select(experiment => new User.Experiment(experiment.name, experiment.@group, experiment.features))); 59 | 60 | List channels = new List(config.followed_hashtags.Count); 61 | channels.AddRange(config.followed_channels.Select(channelname => new Channel(channelname, true))); 62 | 63 | Account.ChannelsFollowLimit = config.channels_follow_limit; 64 | Account.Experiments = experiments; 65 | Account.HomeName = config.home_name; 66 | Account.HomeSet = config.home_set; 67 | Account.FollowedHashtags = config.followed_hashtags; 68 | Account.Location = config.location; 69 | Account.Moderator = config.moderator; 70 | Account.TripleFeedEnabled = config.triple_feed_enabled; 71 | Account.UserType = config.user_type; 72 | Account.Verified = config.verified; 73 | Account.FollowedChannels = channels; 74 | } 75 | 76 | public int GetKarma() 77 | { 78 | string jsonString = Links.GetKarma.ExecuteRequest(Account); 79 | 80 | JsonKarma.RootObject karma = JsonConvert.DeserializeObject(jsonString); 81 | return karma.karma; 82 | } 83 | 84 | 85 | #endregion 86 | 87 | #region Channels 88 | 89 | public IEnumerable GetRecommendedChannels() 90 | { 91 | string jsonString = Links.GetRecommendedChannels.ExecuteRequest(Account, new Dictionary { { "home", "false" } }, payload: new JsonRequestRecommendedChannels()); 92 | 93 | JsonRecommendedChannels.RootObject channels = JsonConvert.DeserializeObject(jsonString); 94 | 95 | List recommendedChannels = new List(); 96 | foreach (JsonRecommendedChannels.Recommended recommended in channels.recommended) 97 | { 98 | if (Account.FollowedChannels.Any(x => x.ChannelName == recommended.channel)) 99 | { 100 | Channel ch = Account.FollowedChannels.First(x => x.ChannelName == recommended.channel).UpdateProperties(recommended.image_url, recommended.followers); 101 | recommendedChannels.Add(ch); 102 | } 103 | else 104 | { 105 | recommendedChannels.Add(new Channel(recommended.channel) { ImageUrl = recommended.image_url, Followers = recommended.followers }); 106 | } 107 | } 108 | 109 | return recommendedChannels; 110 | } 111 | 112 | #endregion 113 | 114 | #region Jodels 115 | 116 | public JodelMainData GetPostLocationCombo(bool stickies = false, bool home = false) 117 | { 118 | string jsonString = Links.GetPostsCombo.ExecuteRequest(Account, new Dictionary 119 | { 120 | { "lat", Account.Place.Latitude.ToString("F",CultureInfo.InvariantCulture) }, 121 | { "lng", Account.Place.Longitude.ToString("F",CultureInfo.InvariantCulture) }, 122 | { "stickies", stickies.ToString().ToLower() }, 123 | { "home", home.ToString().ToLower() } 124 | }); 125 | 126 | JsonJodelsFirstRound.RootObject jodels = JsonConvert.DeserializeObject(jsonString); 127 | JodelMainData data = new JodelMainData { Max = jodels.max }; 128 | data.RecentJodels.AddRange(jodels.recent.Select(r => new JodelPost(r))); 129 | data.RepliedJodels.AddRange(jodels.replied.Select(r => new JodelPost(r))); 130 | data.VotedJodels.AddRange(jodels.voted.Select(v => new JodelPost(v))); 131 | return data; 132 | } 133 | 134 | public JodelMainData GetPostHashtagCombo(string hashtag, bool home = false) 135 | { 136 | string jsonString = Links.GetHashtagCombo.ExecuteRequest(Account, new Dictionary 137 | { 138 | { "hashtag", hashtag}, 139 | { "home", home.ToString().ToLower() } 140 | }); 141 | 142 | JsonJodelsFirstRound.RootObject jodels = JsonConvert.DeserializeObject(jsonString); 143 | JodelMainData data = new JodelMainData { Max = jodels.max }; 144 | data.RecentJodels.AddRange(jodels.recent.Select(r => new JodelPost(r))); 145 | data.RepliedJodels.AddRange(jodels.replied.Select(r => new JodelPost(r))); 146 | data.VotedJodels.AddRange(jodels.voted.Select(v => new JodelPost(v))); 147 | return data; 148 | } 149 | 150 | public JodelMainData GetPostChannelCombo(string channel, bool home = false) 151 | { 152 | string jsonString = Links.GetChannelCombo.ExecuteRequest(Account, new Dictionary 153 | { 154 | { "channel", channel}, 155 | { "home", home.ToString().ToLower() } 156 | }); 157 | 158 | JsonJodelsFirstRound.RootObject jodels = JsonConvert.DeserializeObject(jsonString); 159 | JodelMainData data = new JodelMainData { Max = jodels.max }; 160 | data.RecentJodels.AddRange(jodels.recent.Select(r => new JodelPost(r))); 161 | data.RepliedJodels.AddRange(jodels.replied.Select(r => new JodelPost(r))); 162 | data.VotedJodels.AddRange(jodels.voted.Select(v => new JodelPost(v))); 163 | return data; 164 | } 165 | 166 | public IEnumerable GetRecentPostsAfter(string afterPostId, bool home = false) 167 | { 168 | string jsonString = Links.GetMostRecentPosts.ExecuteRequest(Account, new Dictionary 169 | { 170 | { "after", afterPostId }, 171 | { "lat", Account.Place.Latitude.ToString(CultureInfo.InvariantCulture) }, 172 | { "lng", Account.Place.Longitude.ToString(CultureInfo.InvariantCulture) }, 173 | { "home", home.ToString().ToLower() } 174 | }); 175 | 176 | return JsonConvert.DeserializeObject(jsonString).posts.Select(p => new JodelPost(p)); 177 | } 178 | 179 | 180 | 181 | public JodelPost GetPost(string postId) 182 | { 183 | string jsonString = Links.GetPost.ExecuteRequest(Account, postId: postId); 184 | return new JodelPost(JsonConvert.DeserializeObject(jsonString)); 185 | } 186 | 187 | public JodelPost GetPostDetails(string postId, bool details = true, bool reversed = false, int next = 0) 188 | { 189 | Dictionary parameters = 190 | new Dictionary {{"details", details.ToString().ToLower()}}; 191 | if (next > 0) parameters.Add("reply", next.ToString()); 192 | parameters.Add("reversed", reversed.ToString().ToLower()); 193 | 194 | string jsonString = Links.GetPostDetails.ExecuteRequest(Account, postId: postId, parameters: parameters); 195 | return new JodelPost(JsonConvert.DeserializeObject(jsonString)); 196 | } 197 | 198 | #endregion 199 | 200 | #endregion 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /JodelAPI/JodelAPI/Account.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | using JodelAPI.Json; 8 | using JodelAPI.Objects; 9 | using Newtonsoft.Json; 10 | using Newtonsoft.Json.Linq; 11 | 12 | namespace JodelAPI 13 | { 14 | public class Account 15 | { 16 | private static User _user; 17 | 18 | internal Account(User user) 19 | { 20 | _user = user; 21 | } 22 | 23 | /// 24 | /// Gets the karma. 25 | /// 26 | /// System.Int32. 27 | public int GetKarma() 28 | { 29 | string resp; 30 | using (var client = new MyWebClient()) 31 | { 32 | resp = client.DownloadString(Constants.LinkGetKarma.ToLink()); 33 | } 34 | string result = resp.Substring(resp.LastIndexOf(':') + 1); 35 | return Convert.ToInt32(result.Replace("}", "").Replace("\"", "")); 36 | } 37 | 38 | /// 39 | /// Generates an access token. 40 | /// 41 | /// System.String. 42 | public static Tokens GenerateAccessToken() 43 | { 44 | DateTime dt = DateTime.UtcNow; 45 | string jsonString; 46 | string deviceUid = Helpers.Sha256(Helpers.RandomString(20, true)); 47 | 48 | string stringifiedPayload = @"POST%api.go-tellm.com%443%/api/v2/users/%%" + $"{dt:s}Z" + 49 | @"%%{""device_uid"": """ + deviceUid + @""", ""location"": {""City"": """ + _user.City + 50 | @""", ""loc_accuracy"": 0, ""loc_coordinates"": {""lat"": " + _user.Latitude + 51 | @", ""lng"": " + _user.Longitude + @"}, ""country"": """ + _user.CountryCode + @"""}, " + 52 | @"""client_id"": """ + Constants.ClientId + @"""}"; 53 | 54 | string payload = @"{""device_uid"": """ + deviceUid + @""", ""location"": {""City"": """ + _user.City + 55 | @""", ""loc_accuracy"": 0, ""loc_coordinates"": " + @"{""lat"": " + _user.Latitude + 56 | @", ""lng"": " + _user.Longitude + @"}, ""country"": """ + _user.CountryCode + 57 | @"""}, ""client_id"": """ + Constants.ClientId + @"""}"; 58 | 59 | var keyByte = Encoding.UTF8.GetBytes(Constants.Key); 60 | using (var hmacsha1 = new HMACSHA1(keyByte)) 61 | { 62 | hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(stringifiedPayload)); 63 | 64 | using (var client = new MyWebClient()) 65 | { 66 | client.Headers.Add(Constants.Header.ToHeader(stringifiedPayload, DateTime.UtcNow)); 67 | client.Encoding = Encoding.UTF8; 68 | jsonString = client.UploadString(Constants.LinkGenAt, payload); 69 | } 70 | } 71 | 72 | JsonTokens.RootObject objTokens = JsonConvert.DeserializeObject(jsonString); 73 | 74 | return new Tokens 75 | { 76 | AccessToken = objTokens.access_token, 77 | RefreshToken = objTokens.refresh_token, 78 | ExpireTimestamp = objTokens.expiration_date 79 | }; 80 | } 81 | 82 | public static Tokens GenerateAccessToken(string latitude, string longitude, string city, string countrycode) 83 | { 84 | DateTime dt = DateTime.UtcNow; 85 | string jsonString; 86 | string deviceUid = Helpers.Sha256(Helpers.RandomString(5, true)); 87 | 88 | string stringifiedPayload = @"POST%api.go-tellm.com%443%/api/v2/users/%%" + $"{dt:s}Z" + 89 | @"%%{""device_uid"": """ + deviceUid + @""", ""location"": {""City"": """ + city + 90 | @""", ""loc_accuracy"": 0, ""loc_coordinates"": {""lat"": " + latitude + 91 | @", ""lng"": " + longitude + @"}, ""country"": """ + countrycode + @"""}, " + 92 | @"""client_id"": """ + Constants.ClientId + @"""}"; 93 | 94 | string payload = @"{""device_uid"": """ + deviceUid + @""", ""location"": {""City"": """ + city + 95 | @""", ""loc_accuracy"": 0, ""loc_coordinates"": " + @"{""lat"": " + latitude + 96 | @", ""lng"": " + longitude + @"}, ""country"": """ + countrycode + 97 | @"""}, ""client_id"": """ + Constants.ClientId + @"""}"; 98 | 99 | var keyByte = Encoding.UTF8.GetBytes(Constants.Key); 100 | using (var hmacsha1 = new HMACSHA1(keyByte)) 101 | { 102 | hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(stringifiedPayload)); 103 | 104 | using (var client = new MyWebClient()) 105 | { 106 | client.Headers.Add(Constants.Header.ToHeader(stringifiedPayload, DateTime.UtcNow)); 107 | client.Encoding = Encoding.UTF8; 108 | jsonString = client.UploadString(Constants.LinkGenAt, payload); 109 | } 110 | } 111 | JsonTokens.RootObject objTokens = JsonConvert.DeserializeObject(jsonString); 112 | 113 | return new Tokens 114 | { 115 | AccessToken = objTokens.access_token, 116 | RefreshToken = objTokens.refresh_token, 117 | ExpireTimestamp = objTokens.expiration_date 118 | }; 119 | } 120 | 121 | public static Tokens GenerateAccessToken(User user) 122 | { 123 | DateTime dt = DateTime.UtcNow; 124 | string jsonString; 125 | string deviceUid = Helpers.Sha256(Helpers.RandomString(5, true)); 126 | 127 | string stringifiedPayload = @"POST%api.go-tellm.com%443%/api/v2/users/%%" + $"{dt:s}Z" + 128 | @"%%{""device_uid"": """ + deviceUid + @""", ""location"": {""City"": """ + user.City + 129 | @""", ""loc_accuracy"": 0, ""loc_coordinates"": {""lat"": " + user.Latitude + 130 | @", ""lng"": " + user.Longitude + @"}, ""country"": """ + user.CountryCode + @"""}, " + 131 | @"""client_id"": """ + Constants.ClientId + @"""}"; 132 | 133 | string payload = @"{""device_uid"": """ + deviceUid + @""", ""location"": {""City"": """ + user.City + 134 | @""", ""loc_accuracy"": 0, ""loc_coordinates"": " + @"{""lat"": " + user.Latitude + 135 | @", ""lng"": " + user.Longitude + @"}, ""country"": """ + user.CountryCode + 136 | @"""}, ""client_id"": """ + Constants.ClientId + @"""}"; 137 | 138 | var keyByte = Encoding.UTF8.GetBytes(Constants.Key); 139 | using (var hmacsha1 = new HMACSHA1(keyByte)) 140 | { 141 | hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(stringifiedPayload)); 142 | 143 | using (var client = new MyWebClient()) 144 | { 145 | client.Headers.Add(Constants.Header.ToHeader(stringifiedPayload, DateTime.UtcNow)); 146 | client.Encoding = Encoding.UTF8; 147 | jsonString = client.UploadString(Constants.LinkGenAt, payload); 148 | } 149 | } 150 | 151 | JsonTokens.RootObject objTokens = JsonConvert.DeserializeObject(jsonString); 152 | 153 | return new Tokens 154 | { 155 | AccessToken = objTokens.access_token, 156 | RefreshToken = objTokens.refresh_token, 157 | ExpireTimestamp = objTokens.expiration_date 158 | }; 159 | } 160 | 161 | /// 162 | /// Sets the user location. 163 | /// 164 | /// The access token. 165 | public void SetUserLocation(string accessToken) 166 | { 167 | string payload = 168 | @"{""location"": {""City"": """ + _user.City + @""", ""loc_accuracy"": 0, ""loc_coordinates"": {" + 169 | @"""lat"": " + _user.Latitude + @", ""lng"": " + _user.Longitude + @"}, ""country"": """ + _user.CountryCode + 170 | @"""}, ""name"": """ + _user.City + @"""}"; 171 | var client = new WebClient { Encoding = Encoding.UTF8 }; 172 | client.Headers.Add("Content-Type", "application/json"); 173 | client.UploadString(Constants.LinkUserLocation.Replace("{AT}", accessToken), "PUT", payload); 174 | } 175 | 176 | public void SetAccessToken(string accessToken) 177 | { 178 | _user.AccessToken = accessToken; 179 | } 180 | 181 | /// 182 | /// Refreshes the access token. 183 | /// 184 | /// The token. 185 | /// Tokens. 186 | public Tokens RefreshAccessToken(Tokens token) 187 | { 188 | string plainJson; 189 | const string payload = @"{""refresh_token"": ""{RT}""}"; 190 | using (var client = new MyWebClient()) 191 | { 192 | client.Encoding = Encoding.UTF8; 193 | client.Headers.Add("Content-Type", "application/json"); 194 | plainJson = client.UploadString(Constants.LinkRefreshToken.Replace("{AT}", token.AccessToken), 195 | payload.Replace("{RT}", token.RefreshToken)); 196 | } 197 | 198 | JsonRefreshTokens.RootObject objRefToken = 199 | JsonConvert.DeserializeObject(plainJson); 200 | 201 | return new Tokens 202 | { 203 | AccessToken = objRefToken.access_token, 204 | ExpireTimestamp = objRefToken.expiration_date, 205 | RefreshToken = token.RefreshToken 206 | }; 207 | } 208 | 209 | /// 210 | /// Refreshes the access token. 211 | /// 212 | /// The access token. 213 | /// The refresh token. 214 | /// Tokens. 215 | public Tokens RefreshAccessToken(string accessToken, string refreshToken) 216 | { 217 | string plainJson; 218 | const string payload = @"{""refresh_token"": ""{RT}""}"; 219 | using (var client = new MyWebClient()) 220 | { 221 | client.Encoding = Encoding.UTF8; 222 | client.Headers.Add("Content-Type", "application/json"); 223 | plainJson = client.UploadString(Constants.LinkRefreshToken.Replace("{AT}", accessToken), 224 | payload.Replace("{RT}", refreshToken)); 225 | } 226 | 227 | JsonRefreshTokens.RootObject objRefToken = 228 | JsonConvert.DeserializeObject(plainJson); 229 | 230 | return new Tokens 231 | { 232 | AccessToken = objRefToken.access_token, 233 | ExpireTimestamp = objRefToken.expiration_date, 234 | RefreshToken = refreshToken 235 | }; 236 | } 237 | } 238 | } --------------------------------------------------------------------------------