Commit 8d3621db authored by Thomas's avatar Thomas
Browse files

Fix Nitter instances

parent fae30e63
Loading
Loading
Loading
Loading
+84 −1
Original line number Diff line number Diff line
@@ -14,10 +14,12 @@ package app.fedilab.android.mastodon.client.entities.nitter;
 * 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 androidx.annotation.NonNull;

import org.jsoup.select.Elements;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Namespace;
@@ -29,6 +31,7 @@ import java.net.IDN;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@@ -82,7 +85,8 @@ public class Nitter implements Serializable {
        status.text = feedItem.title;
        status.content = status.content.replaceAll("<img [^>]*src=\"[^\"]+\"[^>]*>", "");
        status.visibility = "public";
        status.created_at = Helper.stringToDateWithFormat(context, feedItem.pubDate, "EEE, dd MMM yyyy HH:mm:ss zzz");
        String dateFormat = "E', 'dd' 'MMM' 'yyyy' 'hh:m:s' GMT'";
        status.created_at = Helper.stringToDateWithFormat(context, feedItem.pubDate, dateFormat);
        status.uri = feedItem.guid;
        status.url = feedItem.link;
        if (!accounts.containsKey(feedItem.creator)) {
@@ -177,4 +181,83 @@ public class Nitter implements Serializable {
    }


    public static Status nitterHTMLParser(Context context, org.jsoup.nodes.Element timelineItem, String nitterInstance) {

        if(timelineItem == null) {
            return null;
        }
        Status status = new Status();
        Account account = new Account();
        String fedilabInstance = "nitter.fedilab.app";


        org.jsoup.nodes.Element messageLink;
        if(timelineItem.select(".quote-text").html().isEmpty()) {
            status.content = timelineItem.select(".tweet-content").html();
            status.text = timelineItem.select(".tweet-content").text();
            status.url = "https://"+ nitterInstance +timelineItem.select(".tweet-link").attr("href");
            messageLink =  timelineItem.select(".tweet-link").first();
        } else {
            status.content = timelineItem.select(".quote-text").html();
            status.text = timelineItem.select(".quote-text").text();
            status.url = "https://"+ nitterInstance +timelineItem.select(".quote-link").attr("href");
            messageLink =  timelineItem.select(".quote-link").first();
        }
        status.uri = status.url;

        String status_id = String.valueOf(ThreadLocalRandom.current().nextLong(10,10000000));;
        if(messageLink != null){
            String[] splitLink = messageLink.attr("href").split("/");
            status_id = splitLink[splitLink.length-1];
        }
        String pubDate = timelineItem.select(".tweet-date").select("a").attr("title");
        org.jsoup.nodes.Element nameElement = timelineItem.select(".fullname").first();
        String name = nameElement!= null?nameElement.text():"";
        org.jsoup.nodes.Element userNameElement = timelineItem.select(".username").first();
        String userName = userNameElement!= null?userNameElement.text().replace("@",""):"";
        String avatar = "https://" + fedilabInstance + timelineItem.select(".avatar").attr("src");
        account.id = userName;
        account.acct = userName;
        if(timelineItem.select(".replying-to").html().isEmpty()) {
            account.username = userName;
            account.display_name = name;
        } else {
            account.display_name = timelineItem.select(".fullname").text() +"&nbsp;" +timelineItem.select(".replying-to").text();
        }

        account.avatar = avatar;
        account.avatar_static = avatar;
        account.url = "https://"+ nitterInstance +"/" + userName;
        status.id = status_id;
        status.account = account;



        Elements imageElements = timelineItem.select(".attachments").select("img");
        Elements videoElements = timelineItem.select(".attachments").select("video");
        ArrayList<Attachment> attachmentList = new ArrayList<>();
        for(org.jsoup.nodes.Element imageElement: imageElements) {
            Attachment attachment = new Attachment();
            attachment.type = "image";
            attachment.url = "https://"+fedilabInstance+imageElement.attr("src");
            attachment.preview_url = "https://"+fedilabInstance+imageElement.attr("src");
            attachment.id = imageElement.attr("src");
            attachmentList.add(attachment);
        }
        for(org.jsoup.nodes.Element videoElement: videoElements) {
            Attachment attachment = new Attachment();
            attachment.type = "video";
            attachment.url = "https://"+fedilabInstance+videoElement.child(0).attr("src");
            attachment.preview_url = "https://"+fedilabInstance+videoElement.attr("poster");
            attachment.id = videoElement.attr("poster");
            attachmentList.add(attachment);
        }
        status.visibility = "public";
        status.media_attachments = attachmentList;
        String dateFormat = "MMM d', 'yyyy' · 'h:m a' UTC'";
        status.created_at = Helper.stringToDateWithFormat(context, pubDate, dateFormat);
        return status;
    }


}
+2 −3
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ import android.provider.OpenableColumns;
import android.text.Html;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
@@ -647,9 +646,9 @@ public class Helper {
     */
    public static Date stringToDateWithFormat(Context context, String stringDate, String format) {
        if (stringDate == null)
            return null;
            return new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.US);
        Date date = null;
        Date date = new Date();
        try {
            date = dateFormat.parse(stringDate);
        } catch (java.text.ParseException ignored) {
+25 −13
Original line number Diff line number Diff line
@@ -58,7 +58,6 @@ import android.os.Looper;
import android.text.Html;
import android.text.SpannableString;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -567,6 +566,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                    }
                    return;
                }
                if (!remote) {
                    Intent intent = new Intent(context, ContextActivity.class);
                    Bundle args = new Bundle();
                    args.putSerializable(Helper.ARG_STATUS, statusToDeal.quote);
@@ -576,6 +576,9 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                        intent.putExtras(bundle);
                        context.startActivity(intent);
                    });
                } else {
                    Helper.openBrowser(context,statusToDeal.quote.url);
                }
            });
            holder.binding.quotedMessage.cardviewContainer.setStrokeColor(ThemeHelper.getAttColor(context, R.attr.colorPrimary));
            holder.binding.quotedMessage.statusContent.setText(
@@ -1453,15 +1456,24 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>

        //--- BOOSTER INFO ---
        if (status.reblog != null) {
            if(status.account.avatar != null) {
                MastodonHelper.loadPPMastodon(holder.binding.statusBoosterAvatar, status.account);

                holder.binding.statusBoosterAvatar.setVisibility(View.VISIBLE);
            } else {
                holder.binding.statusBoosterAvatar.setVisibility(View.GONE);
            }
            holder.binding.statusBoosterDisplayName.setText(
                    status.account.getSpanDisplayName(context,
                            new WeakReference<>(holder.binding.statusBoosterDisplayName)),
                    TextView.BufferType.SPANNABLE);

            holder.binding.statusBoosterInfo.setVisibility(View.VISIBLE);
            if(status.account.acct != null) {
                holder.binding.statusBoosterUsername.setText(String.format("@%s", status.account.acct));
                holder.binding.statusBoosterUsername.setVisibility(View.VISIBLE);
            } else {
                holder.binding.statusBoosterUsername.setVisibility(View.GONE);
            }
        } else {
            holder.binding.statusBoosterInfo.setVisibility(View.GONE);
        }
+23 −17
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package app.fedilab.android.mastodon.ui.fragment.timeline;

import static app.fedilab.android.BaseMainActivity.currentInstance;
import static app.fedilab.android.BaseMainActivity.networkAvailable;
import static app.fedilab.android.mastodon.helper.Helper.TAG;

import android.content.BroadcastReceiver;
import android.content.Context;
@@ -418,7 +419,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
            search = bundle.getString(Helper.ARG_SEARCH_KEYWORD, null);
            searchCache = bundle.getString(Helper.ARG_SEARCH_KEYWORD_CACHE, null);
            pinnedTimeline = (PinnedTimeline) bundle.getSerializable(Helper.ARG_REMOTE_INSTANCE);

            canBeFederated = true;
            if (pinnedTimeline != null && pinnedTimeline.remoteInstance != null) {
                if (pinnedTimeline.remoteInstance.type != RemoteInstance.InstanceType.NITTER) {
                    remoteInstance = pinnedTimeline.remoteInstance.host;
@@ -490,7 +491,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
        initialStatuses = null;
        lockForResumeCall = 0;

        canBeFederated = true;

        retry_for_home_done = false;
        SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
        boolean displayScrollBar = sharedpreferences.getBoolean(getString(R.string.SET_TIMELINE_SCROLLBAR), false);
@@ -562,7 +563,12 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
            }
            //Update the timeline with new statuses
            int insertedStatus;
            if (timelineType != Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC && timelineType != Timeline.TimeLineEnum.TREND_MESSAGE ) {
            if(pinnedTimeline!= null && pinnedTimeline.remoteInstance != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER) {
                insertedStatus = fetched_statuses.statuses.size();
                int fromPosition = timelineStatuses.size();
                timelineStatuses.addAll(fetched_statuses.statuses);
                statusAdapter.notifyItemRangeInserted(fromPosition, insertedStatus);
            } else if (timelineType != Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC && timelineType != Timeline.TimeLineEnum.TREND_MESSAGE ) {
                insertedStatus = updateStatusListWith(fetched_statuses.statuses);
            } else { //Trends cannot be ordered by id
                insertedStatus = fetched_statuses.statuses.size();
@@ -679,8 +685,8 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
        if (max_id == null || (statuses.pagination.max_id != null && Helper.compareTo(statuses.pagination.max_id, max_id) < 0) || timelineType.getValue().startsWith("TREND_")) {
            max_id = statuses.pagination.max_id;
        }
        //For Lemmy pagination
        if (pinnedTimeline != null && pinnedTimeline.remoteInstance != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.LEMMY) {
        //For Lemmy and Nitter pagination
        if (pinnedTimeline != null && pinnedTimeline.remoteInstance != null && (pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.LEMMY || pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER)) {
            max_id = statuses.pagination.max_id;
        }
        if (min_id == null || (statuses.pagination.min_id != null && Helper.compareTo(statuses.pagination.min_id, min_id) > 0)) {
@@ -1066,19 +1072,18 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                                }
                            });
                }
            }//MISSKEY TIMELINES
            else if (pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.MISSKEY) {
            }//LEMMY TIMELINES
            else if (pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.LEMMY) {
                if (direction == null) {
                    timelinesVM.getMisskey(remoteInstance, null, MastodonHelper.statusesPerCall(requireActivity()))
                    timelinesVM.getLemmy(remoteInstance, lemmy_post_id, null, MastodonHelper.statusesPerCall(requireActivity()))
                            .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
                } else if (direction == DIRECTION.BOTTOM) {

                    timelinesVM.getMisskey(remoteInstance, max_id, MastodonHelper.statusesPerCall(requireActivity()))
                    timelinesVM.getLemmy(remoteInstance, lemmy_post_id, max_id, MastodonHelper.statusesPerCall(requireActivity()))
                            .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false, true, fetchStatus));
                } else if (direction == DIRECTION.TOP) {
                    flagLoading = false;
                } else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
                    timelinesVM.getMisskey(remoteInstance, null, MastodonHelper.statusesPerCall(requireActivity()))
                    timelinesVM.getLemmy(remoteInstance, lemmy_post_id, null, MastodonHelper.statusesPerCall(requireActivity()))
                            .observe(getViewLifecycleOwner(), statusesRefresh -> {
                                if (statusAdapter != null) {
                                    dealWithPagination(statusesRefresh, direction, true, true, fetchStatus);
@@ -1087,18 +1092,19 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                                }
                            });
                }
            } //LEMMY TIMELINES
            else if (pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.LEMMY) {
            }//MISSKEY TIMELINES
            else if (pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.MISSKEY) {
                if (direction == null) {
                    timelinesVM.getLemmy(remoteInstance, lemmy_post_id, null, MastodonHelper.statusesPerCall(requireActivity()))
                    timelinesVM.getMisskey(remoteInstance, null, MastodonHelper.statusesPerCall(requireActivity()))
                            .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
                } else if (direction == DIRECTION.BOTTOM) {
                    timelinesVM.getLemmy(remoteInstance, lemmy_post_id, max_id, MastodonHelper.statusesPerCall(requireActivity()))

                    timelinesVM.getMisskey(remoteInstance, max_id, MastodonHelper.statusesPerCall(requireActivity()))
                            .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false, true, fetchStatus));
                } else if (direction == DIRECTION.TOP) {
                    flagLoading = false;
                } else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
                    timelinesVM.getLemmy(remoteInstance, lemmy_post_id, null, MastodonHelper.statusesPerCall(requireActivity()))
                    timelinesVM.getMisskey(remoteInstance, null, MastodonHelper.statusesPerCall(requireActivity()))
                            .observe(getViewLifecycleOwner(), statusesRefresh -> {
                                if (statusAdapter != null) {
                                    dealWithPagination(statusesRefresh, direction, true, true, fetchStatus);
+49 −83

File changed.

Preview size limit exceeded, changes collapsed.

Loading