diff --git a/src/API/Account.vala b/src/API/Account.vala index 8ff8f354d..ac0b39a0e 100644 --- a/src/API/Account.vala +++ b/src/API/Account.vala @@ -119,4 +119,9 @@ public class Tuba.API.Account : Entity, Widgetizable { } } + public Account.empty (string t_id = "") { + Object ( + id: t_id + ); + } } diff --git a/src/API/Entity.vala b/src/API/Entity.vala index 5046ad7b8..7cdd990c5 100644 --- a/src/API/Entity.vala +++ b/src/API/Entity.vala @@ -6,7 +6,7 @@ public class Tuba.Entity : GLib.Object, Widgetizable, Json.Serializable { return true; } - static bool is_spec_valid (ref ParamSpec spec) { + public static bool is_spec_valid (ref ParamSpec spec) { return ParamFlags.WRITABLE in spec.flags; } @@ -178,4 +178,31 @@ public class Tuba.Entity : GLib.Object, Widgetizable, Json.Serializable { return node; } + public static bool des_map_string_string (out Value val, Json.Node node) { + var map = new Gee.HashMap (); + if (!node.is_null ()) { + node.get_object ().foreach_member ((obj, t_key, t_node) => { + map.set (t_key, (string) t_node.get_string ()); + }); + } + val = map; + return true; + } + + public static bool des_map (out Value val, Json.Node node, Type type) { + var map = new Gee.HashMap (); + if (!node.is_null ()) { + node.get_object ().foreach_member ((obj, t_key, t_node) => { + try { + var t_obj = Entity.from_json (type, t_node); + map.set (t_key, t_obj); + } catch (Error e) { + warning (@"Error getting Entity from json: $(e.message)"); + } + }); + } + val = map; + return true; + } + } diff --git a/src/API/Misskey.vala b/src/API/Misskey.vala new file mode 100644 index 000000000..972ecada5 --- /dev/null +++ b/src/API/Misskey.vala @@ -0,0 +1,144 @@ +public class Tuba.API.Misskey.JSON : Object { + public static Json.Builder get_app (string callback_url) { + var builder = new Json.Builder (); + builder.begin_object (); + builder.set_member_name ("name"); + builder.add_string_value (Build.NAME); + + builder.set_member_name ("description"); + builder.add_string_value ("Browse the Fediverse"); + + builder.set_member_name ("permission"); + builder.begin_array (); + builder.add_string_value ("write:user-groups"); + builder.add_string_value ("read:user-groups"); + builder.add_string_value ("read:page-likes"); + builder.add_string_value ("write:page-likes"); + builder.add_string_value ("write:pages"); + builder.add_string_value ("read:pages"); + builder.add_string_value ("write:votes"); + builder.add_string_value ("write:reactions"); + builder.add_string_value ("read:reactions"); + builder.add_string_value ("write:notifications"); + builder.add_string_value ("read:notifications"); + builder.add_string_value ("write:notes"); + builder.add_string_value ("write:mutes"); + builder.add_string_value ("read:mutes"); + builder.add_string_value ("read:account"); + builder.add_string_value ("write:account"); + builder.add_string_value ("read:blocks"); + builder.add_string_value ("write:blocks"); + builder.add_string_value ("read:drive"); + builder.add_string_value ("write:drive"); + builder.add_string_value ("read:favorites"); + builder.add_string_value ("write:favorites"); + builder.add_string_value ("read:following"); + builder.add_string_value ("write:following"); + builder.add_string_value ("read:messaging"); + builder.add_string_value ("write:messaging"); + builder.end_array (); + + builder.set_member_name ("callbackUrl"); + builder.add_string_value (callback_url); + + builder.end_object (); + + return builder; + } + + public static Json.Builder get_session_generate (string secret) { + var builder = new Json.Builder (); + builder.begin_object (); + + builder.set_member_name ("appSecret"); + builder.add_string_value (secret); + + builder.end_object (); + + return builder; + } + + public static Json.Builder get_session_userkey (string secret, string token) { + var builder = new Json.Builder (); + builder.begin_object (); + + builder.set_member_name ("appSecret"); + builder.add_string_value (secret); + + builder.set_member_name ("token"); + builder.add_string_value (token); + + builder.end_object (); + + return builder; + } + + public static Json.Builder get_show_userid (string userid) { + var builder = new Json.Builder (); + builder.begin_object (); + + builder.set_member_name ("userId"); + builder.add_string_value (userid); + + builder.end_object (); + + return builder; + } + + public static Json.Builder get_timeline (int limit = 20, string? userId = null) { + var builder = new Json.Builder (); + builder.begin_object (); + + // builder.set_member_name ("i"); + // builder.add_string_value (accounts.active.i); + + builder.set_member_name ("limit"); + builder.add_int_value (limit); + + if (userId != null) { + builder.set_member_name ("userId"); + builder.add_string_value (userId); + } + + builder.end_object (); + + return builder; + } + + public static Json.Builder get_children (string noteId) { + var builder = new Json.Builder (); + builder.begin_object (); + + // builder.set_member_name ("limit"); + // builder.add_int_value (limit); + + builder.set_member_name ("noteId"); + builder.add_string_value (noteId); + + builder.end_object (); + + return builder; + } + + public static Json.Builder get_delete_note (string noteId) { + var builder = new Json.Builder (); + builder.begin_object (); + + builder.set_member_name ("noteId"); + builder.add_string_value (noteId); + + builder.end_object (); + + return builder; + } +} + +public class Tuba.API.Misskey.Utils : Object { + public static string generate_i (string secret, string access_token) { + string pre_c = @"$access_token$secret"; + Checksum checksum = new Checksum (ChecksumType.SHA256); + + checksum.update (pre_c.data, -1); + return checksum.get_string (); + } +} diff --git a/src/API/Misskey/AiChanify.vala b/src/API/Misskey/AiChanify.vala new file mode 100644 index 000000000..fdbbe4a7b --- /dev/null +++ b/src/API/Misskey/AiChanify.vala @@ -0,0 +1,5 @@ +public interface Tuba.API.Misskey.AiChanify : GLib.Object, Widgetizable { + public virtual Entity to_mastodon () throws Oopsie { + throw new Tuba.Oopsie.INTERNAL ("Ai Chan didn't provide a Mastodon entity!"); + } +} diff --git a/src/API/Misskey/Bookmark.vala b/src/API/Misskey/Bookmark.vala new file mode 100644 index 000000000..f4b76566e --- /dev/null +++ b/src/API/Misskey/Bookmark.vala @@ -0,0 +1,11 @@ +public class Tuba.API.Misskey.Bookmark : Entity, Widgetizable, AiChanify { + public API.Misskey.Note note { get; set; } + + public override Entity to_mastodon () { + return note.to_mastodon (); + } + + public override Gtk.Widget to_widget () { + return to_mastodon ().to_widget (); + } +} diff --git a/src/API/Misskey/Emoji.vala b/src/API/Misskey/Emoji.vala new file mode 100644 index 000000000..627ee3649 --- /dev/null +++ b/src/API/Misskey/Emoji.vala @@ -0,0 +1,4 @@ +public class Tuba.API.Misskey.Emoji : Entity { + public string name { get; set; } + public string url { get; set; } +} diff --git a/src/API/Misskey/Favorite.vala b/src/API/Misskey/Favorite.vala new file mode 100644 index 000000000..4e089dac6 --- /dev/null +++ b/src/API/Misskey/Favorite.vala @@ -0,0 +1,12 @@ +public class Tuba.API.Misskey.Favorite : Entity, Widgetizable, AiChanify { + public string kind { get; set; } + public API.Misskey.Note note { get; set; } + + public override Entity to_mastodon () { + return note.to_mastodon (); + } + + public override Gtk.Widget to_widget () { + return to_mastodon ().to_widget (); + } +} diff --git a/src/API/Misskey/Note.vala b/src/API/Misskey/Note.vala new file mode 100644 index 000000000..4e5a6cb65 --- /dev/null +++ b/src/API/Misskey/Note.vala @@ -0,0 +1,88 @@ +public class Tuba.API.Misskey.Note : Entity, Widgetizable, Json.Serializable, AiChanify { + ~Note () { + message (@"[OBJ] Destroyed $uri"); + } + + public string id { get; set; } + public string createdAt { get; set; default = ""; } + public string text { get; set; default = ""; } + public string? cw { get; set; default = null; } + public API.Misskey.User user { get; set; } + public string? replyId { get; set; default = null; } + public string visibility { get; set; default = settings.default_post_visibility; } + public Gee.ArrayList? mentions { get; set; default = null; } + public Gee.ArrayList? fileIds { get; set; default = null; } + // public API.Poll? poll { get; set; default = null; } + public Gee.ArrayList? emojis { get; set; } + public Gee.HashMap? reactions { get; set; default = null; } + public int64 renotesCount { get; set; default = 0; } + public int64 repliesCount { get; set; default = 0; } + public string uri { get; set; } + public string url { get; set; } + public API.Misskey.Note? renote { get; set; default = null; } + + public static Note from (Json.Node node) throws Error { + return Entity.from_json (typeof (API.Misskey.Note), node) as API.Misskey.Note; + } + + public override bool deserialize_property (string prop, out Value val, ParamSpec spec, Json.Node node) { + var success = default_deserialize_property (prop, out val, spec, node); + + var type = spec.value_type; + if (val.type () == Type.INVALID) { + val.init (type); + spec.set_value_default (ref val); + type = spec.value_type; + } + + if (type.is_a (typeof (Gee.ArrayList))) { + Type contains; + + switch (prop) { + case "mentions": + return Entity.des_list_string (out val, node); + case "emojis": + contains = typeof (API.Misskey.Emoji); + break; + case "reactions": + return Entity.des_map_string_string (out val, node); + default: + contains = typeof (Entity); + break; + } + return des_list (out val, node, contains); + } + + return success; + } + + public override Entity to_mastodon () { + var masto_status = new API.Status.empty (); + masto_status.id = id; + masto_status.account = (API.Account) user.to_mastodon (); + masto_status.spoiler_text = cw; + masto_status.in_reply_to_id = replyId; + masto_status.content = text; + masto_status.replies_count = repliesCount; + masto_status.reblogs_count = renotesCount; + masto_status.visibility = visibility; + masto_status.uri = uri; + masto_status.created_at = createdAt; + + if (renote != null) { + var reblog_status = renote.to_mastodon () as API.Status; + + if (text == null && (fileIds == null || fileIds.size == 0)) { + masto_status.reblog = reblog_status; + } else { + masto_status.quote = reblog_status; + } + } + + return masto_status; + } + + public override Gtk.Widget to_widget () { + return to_mastodon ().to_widget (); + } +} diff --git a/src/API/Misskey/User.vala b/src/API/Misskey/User.vala new file mode 100644 index 000000000..50134e26e --- /dev/null +++ b/src/API/Misskey/User.vala @@ -0,0 +1,40 @@ +public class Tuba.API.Misskey.User : Entity, Widgetizable, AiChanify, Json.Serializable { + public string id { get; set; } + public string name { get; set; } + public string username { get; set; } + public string host { get; set; } + public string avatarUrl { get; set; } + public string description { get; set; } + public bool isLocked { get; set; } + public string url { get; set; } + public string createdAt { get; set; } + public string bannerUrl { get; set; } + public int64 followersCount { get; set; } + public int64 followingCount { get; set; } + public int64 notesCount { get; set; } + + public static User from (Json.Node node) throws Error { + return Entity.from_json (typeof (API.Misskey.User), node) as API.Misskey.User; + } + + public override Entity to_mastodon () { + var masto_acc = new API.Account.empty (id); + masto_acc.username = username; + masto_acc.acct = host != null ? @"$username@$host" : username; + masto_acc.note = description ?? ""; + masto_acc.locked = isLocked; + masto_acc.header = bannerUrl; + masto_acc.avatar = avatarUrl; + masto_acc.url = url ?? @"$host/@$username"; + masto_acc.followers_count = followersCount; + masto_acc.following_count = followingCount; + masto_acc.statuses_count = notesCount; + masto_acc.created_at = createdAt; + + return masto_acc; + } + + public override Gtk.Widget to_widget () { + return to_mastodon ().to_widget (); + } +} diff --git a/src/API/Misskey/meson.build b/src/API/Misskey/meson.build new file mode 100644 index 000000000..f3ca8bc0b --- /dev/null +++ b/src/API/Misskey/meson.build @@ -0,0 +1,8 @@ +sources += files( + 'AiChanify.vala', + 'Bookmark.vala', + 'Favorite.vala', + 'Emoji.vala', + 'Note.vala', + 'User.vala', +) \ No newline at end of file diff --git a/src/API/Status.vala b/src/API/Status.vala index 330caba76..867526caf 100644 --- a/src/API/Status.vala +++ b/src/API/Status.vala @@ -193,7 +193,10 @@ public class Tuba.API.Status : Entity, Widgetizable { } public Request annihilate () { - return new Request.DELETE (@"/api/v1/statuses/$id") - .with_account (accounts.active); + // return new Request.DELETE (@"/api/v1/statuses/$id") + // .with_account (accounts.active); + return new Request.POST ("/api/notes/delete") + .with_account (accounts.active) + .body_json (API.Misskey.JSON.get_delete_note (id)); } } diff --git a/src/API/meson.build b/src/API/meson.build index 0072e02d2..05956f8d9 100644 --- a/src/API/meson.build +++ b/src/API/meson.build @@ -12,6 +12,7 @@ sources += files( 'Instance.vala', 'List.vala', 'Mention.vala', + 'Misskey.vala', 'Notification.vala', 'PeerTube.vala', 'Pleroma.vala', @@ -30,5 +31,6 @@ subdir('Account') subdir('BookWyrm') subdir('Funkwhale') subdir('Instance') +subdir('Misskey') subdir('PeerTube') subdir('Status') diff --git a/src/Dialogs/NewAccount.vala b/src/Dialogs/NewAccount.vala index 0e58ab0c9..4195d0a8a 100644 --- a/src/Dialogs/NewAccount.vala +++ b/src/Dialogs/NewAccount.vala @@ -125,22 +125,42 @@ public class Tuba.Dialogs.NewAccount: Adw.Window { async void register_client () throws Error { message ("Registering client"); - var msg = new Request.POST ("/api/v1/apps") + // var msg = new Request.POST (@"/api/v1/apps") + // .with_account (account) + // .with_form_data ("client_name", Build.NAME) + // .with_form_data ("redirect_uris", redirect_uri = setup_redirect_uri ()) + // .with_form_data ("scopes", scopes) + // .with_form_data ("website", Build.WEBSITE); + + var msg = new Request.POST ("/api/app/create") .with_account (account) - .with_form_data ("client_name", Build.NAME) - .with_form_data ("redirect_uris", redirect_uri = setup_redirect_uri ()) - .with_form_data ("scopes", SCOPES) - .with_form_data ("website", Build.WEBSITE); + .body_json (Tuba.API.Misskey.JSON.get_app (setup_redirect_uri ())); yield msg.await (); var parser = Network.get_parser_from_inputstream (msg.response_body); var root = network.parse (parser); - account.client_id = root.get_string_member ("client_id"); - account.client_secret = root.get_string_member ("client_secret"); + // account.client_id = root.get_string_member ("client_id"); + // account.client_secret = root.get_string_member ("client_secret"); + account.client_id = root.get_string_member ("id"); + account.client_secret = root.get_string_member ("secret"); message ("OK: Instance registered client"); deck.visible_child = code_step; - open_confirmation_page (); + // open_confirmation_page (); + + var mk_msg = new Request.POST ("/api/auth/session/generate") + .with_account (account) + .body_json (Tuba.API.Misskey.JSON.get_session_generate (account.client_secret)); + yield mk_msg.await (); + + parser = Network.get_parser_from_inputstream (mk_msg.response_body); + root = network.parse (parser); + var callbackurl = root.get_string_member ("url"); + warning (account.client_id); + warning (account.client_secret); + warning (callbackurl); + Host.open_uri (callbackurl); + // Process.exit (0); } void open_confirmation_page () { @@ -156,23 +176,32 @@ public class Tuba.Dialogs.NewAccount: Adw.Window { throw new Oopsie.USER (_("Please enter a valid authorization code")); message ("Requesting access token"); - var token_req = new Request.POST ("/oauth/token") + // var token_req = new Request.POST (@"/oauth/token") + // .with_account (account) + // .with_param ("client_id", account.client_id) + // .with_param ("client_secret", account.client_secret) + // .with_param ("redirect_uri", redirect_uri) + // .with_param ("grant_type", "authorization_code") + // .with_param ("code", code_entry.text); + // yield token_req.await (); + + warning (account.client_secret); + warning (code_entry.text); + var token_req = new Request.POST ("/api/auth/session/userkey") .with_account (account) - .with_form_data ("client_id", account.client_id) - .with_form_data ("client_secret", account.client_secret) - .with_form_data ("redirect_uri", redirect_uri) - .with_form_data ("grant_type", "authorization_code") - .with_form_data ("code", code_entry.text); + .body_json (Tuba.API.Misskey.JSON.get_session_userkey (account.client_secret, code_entry.text)); yield token_req.await (); var parser = Network.get_parser_from_inputstream (token_req.response_body); var root = network.parse (parser); - account.access_token = root.get_string_member ("access_token"); + // account.access_token = root.get_string_member ("access_token"); + account.access_token = root.get_string_member ("accessToken"); + account.i = API.Misskey.Utils.generate_i (account.access_token, account.client_secret); if (account.access_token == null) throw new Oopsie.INSTANCE (_("Instance failed to authorize the access token")); - yield account.verify_credentials (); + yield account.verify_credentials (root.get_member ("user").get_object ().get_string_member ("id")); account = accounts.create_account (account.to_json ()); diff --git a/src/Services/Accounts/AccountStore.vala b/src/Services/Accounts/AccountStore.vala index a533023ef..196c1b144 100644 --- a/src/Services/Accounts/AccountStore.vala +++ b/src/Services/Accounts/AccountStore.vala @@ -83,7 +83,7 @@ public abstract class Tuba.AccountStore : GLib.Object { return; } else { message (@"Activating $(account.handle)…"); - account.verify_credentials.begin ((obj, res) => { + account.verify_credentials.begin (null, (obj, res) => { try { account.verify_credentials.end (res); account.error = null; @@ -135,18 +135,18 @@ public abstract class Tuba.AccountStore : GLib.Object { public Gee.ArrayList backend_tests = new Gee.ArrayList (); public async void guess_backend (InstanceAccount account) throws GLib.Error { - var req = new Request.GET ("/api/v1/instance") - .with_account (account); - yield req.await (); - - var parser = Network.get_parser_from_inputstream (req.response_body); - var root = network.parse (parser); - - string? backend = null; - backend_tests.foreach (test => { - backend = test.get_backend (root); - return true; - }); + // var req = new Request.GET ("/api/v1/instance") + // .with_account (account); + // yield req.await (); + + // var parser = Network.get_parser_from_inputstream (req.response_body); + // var root = network.parse (parser); + + string? backend = "Mastodon"; + // backend_tests.foreach (test => { + // backend = test.get_backend (root); + // return true; + // }); if (backend == null) throw new Oopsie.INTERNAL ("This instance is unsupported."); diff --git a/src/Services/Accounts/InstanceAccount.vala b/src/Services/Accounts/InstanceAccount.vala index 17edfcd02..043ce084a 100644 --- a/src/Services/Accounts/InstanceAccount.vala +++ b/src/Services/Accounts/InstanceAccount.vala @@ -25,6 +25,7 @@ public class Tuba.InstanceAccount : API.Account, Streamable { public string? client_id { get; set; } public string? client_secret { get; set; } public string? access_token { get; set; } + public string? i { get; set; default=null; } public Error? error { get; set; } //TODO: use this field when server invalidates the auth token public GLib.ListStore known_places = new GLib.ListStore (typeof (Place)); @@ -120,13 +121,20 @@ public class Tuba.InstanceAccount : API.Account, Streamable { return Entity.from_json (type, node); } - public async void verify_credentials () throws Error { - var req = new Request.GET ("/api/v1/accounts/verify_credentials").with_account (this); + public async void verify_credentials (string? t_id = null) throws Error { + // var req = new Request.GET ("/api/v1/accounts/verify_credentials").with_account (this); + warning (t_id); + var req = new Request.POST ("/api/users/show") + .with_account (this) + .body_json (API.Misskey.JSON.get_show_userid (t_id)); yield req.await (); var parser = Network.get_parser_from_inputstream (req.response_body); var node = network.parse_node (parser); - var updated = API.Account.from (node); + // var updated = API.Account.from (node); + var mk_account = API.Misskey.User.from (node); + mk_account.host = this.instance; + var updated = (API.Account) mk_account.to_mastodon (); patch (updated); message (@"$handle: profile updated"); diff --git a/src/Services/Accounts/SecretAccountStore.vala b/src/Services/Accounts/SecretAccountStore.vala index f385b3270..0de09e8cb 100644 --- a/src/Services/Accounts/SecretAccountStore.vala +++ b/src/Services/Accounts/SecretAccountStore.vala @@ -131,6 +131,9 @@ public class Tuba.SecretAccountStore : AccountStore { var generator = new Json.Generator (); account.instance_info = null; account.instance_emojis = null; + account.t_connection_url = null; + account.source = null; + generator.set_root (account.to_json ()); var secret = generator.to_data (null); // translators: The variable is the backend like "Mastodon" diff --git a/src/Views/Bookmarks.vala b/src/Views/Bookmarks.vala index 9b37be05d..680e0cadb 100644 --- a/src/Views/Bookmarks.vala +++ b/src/Views/Bookmarks.vala @@ -2,10 +2,11 @@ public class Tuba.Views.Bookmarks : Views.Timeline { public Bookmarks () { Object ( - url: "/api/v1/bookmarks", + url: "/api/i/favorites", label: _("Bookmarks"), icon: "tuba-bookmarks-symbolic" ); + accepts = typeof (API.Misskey.Bookmark); } } diff --git a/src/Views/Favorites.vala b/src/Views/Favorites.vala index 97c0206de..2f7704c66 100644 --- a/src/Views/Favorites.vala +++ b/src/Views/Favorites.vala @@ -2,9 +2,11 @@ public class Tuba.Views.Favorites : Views.Timeline { public Favorites () { Object ( - url: "/api/v1/favourites", - label: _("Favorites") + url: "/api/users/reactions", + label: _("Favorites"), + with_user_id: true ); + accepts = typeof (API.Misskey.Favorite); } } diff --git a/src/Views/Federated.vala b/src/Views/Federated.vala index ebdfccda8..e72655d89 100644 --- a/src/Views/Federated.vala +++ b/src/Views/Federated.vala @@ -2,11 +2,12 @@ public class Tuba.Views.Federated : Views.Timeline { public Federated () { Object ( - url: "/api/v1/timelines/public", + url: "/api/notes/global-timeline", is_public: true, label: _("Federated"), icon: "tuba-globe-symbolic" ); + accepts = typeof (API.Misskey.Note); } public override string? get_stream_url () { diff --git a/src/Views/Home.vala b/src/Views/Home.vala index a164a72d6..e81b31840 100644 --- a/src/Views/Home.vala +++ b/src/Views/Home.vala @@ -1,10 +1,11 @@ public class Tuba.Views.Home : Views.Timeline { public Home () { Object ( - url: "/api/v1/timelines/home", + url: "/api/notes/timeline", label: _("Home"), icon: "tuba-home-symbolic" ); + accepts = typeof (API.Misskey.Note); } public override string? get_stream_url () { diff --git a/src/Views/Local.vala b/src/Views/Local.vala index 36a578abe..5110da3fb 100644 --- a/src/Views/Local.vala +++ b/src/Views/Local.vala @@ -1,15 +1,19 @@ -public class Tuba.Views.Local : Views.Federated { +public class Tuba.Views.Local : Views.Timeline { + public Local () { + Object ( + url: "/api/notes/local-timeline", + is_public: true, + label: _("Local"), + icon: "tuba-network-server-symbolic" + ); + accepts = typeof (API.Misskey.Note); + } - public Local () { - label = _("Local"); - icon = "tuba-network-server-symbolic"; - } - - public override Request append_params (Request r) { - var req = base.append_params (r); - req.with_param ("local", "true"); - return req; - } + // public override Request append_params (Request r) { + // var req = base.append_params (r); + // req.with_param ("local", "true"); + // return req; + // } public override string? get_stream_url () { return account != null diff --git a/src/Views/Notifications.vala b/src/Views/Notifications.vala index a6cfd9a2e..662011aa6 100644 --- a/src/Views/Notifications.vala +++ b/src/Views/Notifications.vala @@ -8,7 +8,7 @@ public class Tuba.Views.Notifications : Views.Timeline, AccountHolder, Streamabl private Binding badge_number_binding; public Notifications () { Object ( - url: "/api/v1/notifications", + url: "/api/i/notifications", label: _("Notifications"), icon: "tuba-bell-symbolic", badge_number: 0, diff --git a/src/Views/Timeline.vala b/src/Views/Timeline.vala index d20fe5a3d..5d8df6e9e 100644 --- a/src/Views/Timeline.vala +++ b/src/Views/Timeline.vala @@ -7,6 +7,7 @@ public class Tuba.Views.Timeline : AccountHolder, Streamable, Views.ContentBase public bool is_public { get; construct set; default = false; } public Type accepts { get; set; default = typeof (API.Status); } public bool use_queue { get; set; default = true; } + public bool with_user_id { get; set; default=false; } protected InstanceAccount? account { get; set; default = null; } @@ -165,20 +166,45 @@ public class Tuba.Views.Timeline : AccountHolder, Streamable, Views.ContentBase } public virtual bool request () { - append_params (new Request.GET (get_req_url ())) + // append_params (new Request.GET (get_req_url ())) + // .with_account (account) + // .with_ctx (this) + // .then ((sess, msg, in_stream) => { + // var parser = Network.get_parser_from_inputstream(in_stream); + + // Object[] to_add = {}; + // Network.parse_array (msg, parser, node => { + // var e = entity_cache.lookup_or_insert (node, accepts); + // to_add += e; + // }); + // model.splice (model.get_n_items (), 0, to_add); + + // get_pages (msg.response_headers.get_one ("Link")); + // on_content_changed (); + // on_request_finish (); + // }) + // .on_error (on_error) + // .exec (); + + new Request.POST (get_req_url ()) .with_account (account) .with_ctx (this) + .body_json (Tuba.API.Misskey.JSON.get_timeline (settings.timeline_page_size, with_user_id ? account.id : null)) .then ((sess, msg, in_stream) => { var parser = Network.get_parser_from_inputstream (in_stream); Object[] to_add = {}; Network.parse_array (msg, parser, node => { var e = entity_cache.lookup_or_insert (node, accepts); - to_add += e; + + var e_aichanified = e as API.Misskey.AiChanify; + if (e_aichanified != null) { + to_add += (Entity) e_aichanified.to_mastodon (); + } }); model.splice (model.get_n_items (), 0, to_add); - get_pages (msg.response_headers.get_one ("Link")); + // get_pages (msg.response_headers.get_one ("Link")); on_content_changed (); on_request_finish (); }) diff --git a/vala-lint.conf b/vala-lint.conf index a8e60925c..7cda50b38 100644 --- a/vala-lint.conf +++ b/vala-lint.conf @@ -1,2 +1,3 @@ [Checks] use-of-tabs=off +naming-convention=off