With Nitter

This commit is contained in:
Thomas 2022-06-29 14:13:33 +02:00
parent 2caa24c79b
commit f47866660e
5 changed files with 107 additions and 88 deletions

View file

@ -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
);

View file

@ -1,18 +1,31 @@
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,58 +98,73 @@ 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;
}
Pattern imgPattern = Pattern.compile("<img [^>]*src=\"([^\"]+)\"[^>]*>");
Matcher matcher = imgPattern.matcher(feedItem.description);
String description = feedItem.description;
ArrayList<Attachment> attachmentList = new ArrayList<>();
while (matcher.find()) {
description = description.replaceAll(Pattern.quote(matcher.group()), "");
Attachment attachment = new Attachment();
attachment.type = "image";
attachment.url = matcher.group(1);
attachment.preview_url = matcher.group(1);
attachment.id = matcher.group(1);
attachmentList.add(attachment);
if (feedItem.description != null) {
Pattern imgPattern = Pattern.compile("<img [^>]*src=\"([^\"]+)\"[^>]*>");
Matcher matcher = imgPattern.matcher(feedItem.description);
String description = feedItem.description;
ArrayList<Attachment> attachmentList = new ArrayList<>();
while (matcher.find()) {
description = description.replaceAll(Pattern.quote(matcher.group()), "");
Attachment attachment = new Attachment();
attachment.type = "image";
attachment.url = matcher.group(1);
attachment.preview_url = matcher.group(1);
attachment.id = matcher.group(1);
attachmentList.add(attachment);
}
status.media_attachments = attachmentList;
}
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;
}
}
}

View file

@ -1,36 +0,0 @@
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;
}
}

View file

@ -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

View file

@ -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);
}