Commit f4786666 authored by Thomas's avatar Thomas
Browse files

With Nitter

parent 2caa24c7
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import app.fedilab.android.client.entities.api.MastodonList;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.misskey.MisskeyNote;
import app.fedilab.android.client.entities.nitter.Nitter;
import app.fedilab.android.client.entities.nitter.NitterAccount;
import app.fedilab.android.client.entities.peertube.PeertubeVideo;
import retrofit2.Call;
import retrofit2.http.Body;
@@ -233,7 +232,7 @@ public interface MastodonTimelinesService {
    );

    @GET("{account}/rss")
    Call<NitterAccount> getNitterAccount(
    Call<Nitter> getNitterAccount(
            @Path("account") String account
    );

+80 −46
Original line number Diff line number Diff line
package app.fedilab.android.client.entities.nitter;

/* Copyright 2022 Thomas Schneider
 *
 * This file is a part of Fedilab
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with Fedilab; if not,
 * see <http://www.gnu.org/licenses>. */

import android.content.Context;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import androidx.annotation.NonNull;

import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Path;
import org.simpleframework.xml.Root;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -27,19 +40,26 @@ import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;

@Root(name = "rss", strict = false)
public class Nitter implements Serializable {


    public static HashMap<String, NitterAccount> accounts = new HashMap<>();
    @Element(name = "channel")
    public Channel channel;
    public static HashMap<String, Nitter> accounts = new HashMap<>();

    @Element(name = "title")
    @Path("channel")
    public String title;
    @Element(name = "image")
    @Path("channel")
    public Image image;
    @ElementList(name = "item", inline = true)
    @Path("channel")
    public List<FeedItem> mFeedItems;

    public static MastodonTimelinesService initInstanceXMLOnly(Context context, String instance) {
        Gson gson = new GsonBuilder().setDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").create();

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
@@ -48,7 +68,6 @@ public class Nitter implements Serializable {
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://" + instance)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .client(okHttpClient)
                .build();
@@ -57,21 +76,21 @@ public class Nitter implements Serializable {

    public static Status convert(Context context, String instance, FeedItem feedItem) {
        Status status = new Status();
        status.id = feedItem.pubDate.toString();
        status.id = feedItem.pubDate;
        status.content = feedItem.title;
        status.text = feedItem.title;
        status.visibility = "public";
        status.created_at = feedItem.pubDate;
        status.created_at = Helper.stringToDateWithFormat(context, feedItem.pubDate, "EEE, dd MMM yyyy HH:mm:ss zzz");
        status.uri = feedItem.guid;
        status.url = feedItem.link;
        if (feedItem.creator != null && !accounts.containsValue(feedItem.creator)) {
        if (!accounts.containsValue(feedItem.creator)) {
            MastodonTimelinesService mastodonTimelinesService = initInstanceXMLOnly(context, instance);
            Call<NitterAccount> accountCall = mastodonTimelinesService.getNitterAccount(instance);
            Call<Nitter> accountCall = mastodonTimelinesService.getNitterAccount(feedItem.creator.replace("@", ""));
            if (accountCall != null) {
                try {
                    Response<NitterAccount> publicTlResponse = accountCall.execute();
                    Response<Nitter> publicTlResponse = accountCall.execute();
                    if (publicTlResponse.isSuccessful()) {
                        NitterAccount nitterAccount = publicTlResponse.body();
                        Nitter nitterAccount = publicTlResponse.body();
                        accounts.put(feedItem.creator, nitterAccount);
                    }
                } catch (Exception e) {
@@ -79,20 +98,21 @@ public class Nitter implements Serializable {
                }
            }
        }
        NitterAccount nitterAccount = accounts.get(feedItem.creator);
        Nitter nitterAccount = accounts.get(feedItem.creator);
        if (nitterAccount != null) {
            app.fedilab.android.client.entities.api.Account account = new app.fedilab.android.client.entities.api.Account();
            String[] names = nitterAccount.channel.image.title.split("/");
            String[] names = nitterAccount.image.title.split("/");
            account.id = feedItem.guid;
            account.acct = names[1];
            account.username = names[1];
            account.display_name = names[0];
            account.avatar = nitterAccount.channel.image.url;
            account.avatar_static = nitterAccount.channel.image.url;
            account.url = nitterAccount.channel.image.link;
            account.avatar = nitterAccount.image.url;
            account.avatar_static = nitterAccount.image.url;
            account.url = nitterAccount.image.link;
            status.account = account;
        }

        if (feedItem.description != null) {
            Pattern imgPattern = Pattern.compile("<img [^>]*src=\"([^\"]+)\"[^>]*>");
            Matcher matcher = imgPattern.matcher(feedItem.description);
            String description = feedItem.description;
@@ -107,30 +127,44 @@ public class Nitter implements Serializable {
                attachmentList.add(attachment);
            }
            status.media_attachments = attachmentList;

        }
        return status;
    }

    @Root(name = "channel", strict = false)
    public static class Channel implements Serializable {
        @ElementList(name = "item")
        public List<FeedItem> mFeedItems;
    @Root(name = "image", strict = false)
    public static class Image implements Serializable {
        @Element(name = "title")
        public String title;
        @Element(name = "url")
        public String url;
        @Element(name = "link")
        public String link;
    }

    @Root(name = "item", strict = false)
    public static class FeedItem implements Serializable {
        @ElementList(name = "dc:creator", required = false)
        @Namespace(prefix = "dc")
        @Element(name = "creator", required = false)
        public String creator;
        @ElementList(name = "title")
        @Element(name = "title", required = false)
        public String title;
        @ElementList(name = "description", required = false)
        @Element(name = "description", required = false)
        public String description;
        @ElementList(name = "pubDate")
        public Date pubDate;
        @ElementList(name = "guid", required = false)
        @Element(name = "pubDate", required = false)
        public String pubDate;
        @Element(name = "guid", required = false)
        public String guid;
        @ElementList(name = "link", required = false)
        @Element(name = "link", required = false)
        public String link;

        @NonNull
        @Override
        public String toString() {
            return "creator: " + creator + "\r" + "title: " + title + "\r" + "description: "
                    + description + "\r" + "pubDate: " + pubDate + "\r"
                    + "guid: " + guid + "\r" + "link: " + link;
        }
    }


}
+0 −36
Original line number Diff line number Diff line
package app.fedilab.android.client.entities.nitter;


import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

import java.io.Serializable;
import java.util.HashMap;

@Root(name = "rss", strict = false)
public class NitterAccount implements Serializable {


    public static HashMap<String, NitterAccount> accounts = new HashMap<>();
    @Element(name = "channel")
    public Channel channel;

    @Root(name = "channel", strict = false)
    public static class Channel implements Serializable {
        @Element(name = "image")
        public Image image;

    }

    @Root(name = "image", strict = false)
    public static class Image implements Serializable {
        @Element(name = "title")
        public String title;
        @Element(name = "url")
        public String url;
        @Element(name = "link")
        public String link;
    }


}
+24 −0
Original line number Diff line number Diff line
@@ -590,6 +590,30 @@ public class Helper {
        return date;
    }

    /**
     * Convert String date from db to Date Object
     *
     * @param stringDate date to convert
     * @return Date
     */
    public static Date stringToDateWithFormat(Context context, String stringDate, String format) {
        if (stringDate == null)
            return null;
        Locale userLocale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            userLocale = context.getResources().getConfiguration().getLocales().get(0);
        } else {
            userLocale = context.getResources().getConfiguration().locale;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(format, userLocale);
        Date date = null;
        try {
            date = dateFormat.parse(stringDate);
        } catch (java.text.ParseException ignored) {

        }
        return date;
    }

    /**
     * Converts dp to pixel
+2 −4
Original line number Diff line number Diff line
@@ -94,10 +94,8 @@ public class TimelinesVM extends AndroidViewModel {
    }

    private MastodonTimelinesService initInstanceXMLOnly(String instance) {
        Gson gson = new GsonBuilder().setDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").create();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://" + instance)
                //.addConverterFactory(GsonConverterFactory.create(gson))
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .client(okHttpClient)
                .build();
@@ -180,8 +178,8 @@ public class TimelinesVM extends AndroidViewModel {
                    if (publicTlResponse.isSuccessful()) {
                        Nitter rssResponse = publicTlResponse.body();
                        List<Status> statusList = new ArrayList<>();
                        if (rssResponse != null && rssResponse.channel != null && rssResponse.channel.mFeedItems != null) {
                            for (Nitter.FeedItem feedItem : rssResponse.channel.mFeedItems) {
                        if (rssResponse != null && rssResponse.mFeedItems != null) {
                            for (Nitter.FeedItem feedItem : rssResponse.mFeedItems) {
                                Status status = Nitter.convert(getApplication(), instance, feedItem);
                                statusList.add(status);
                            }