From a3d8201d97f889ed9909f4fc327b166477fdcec5 Mon Sep 17 00:00:00 2001 From: nuclearfog Date: Thu, 22 Dec 2022 15:31:32 +0100 Subject: [PATCH] added location database table, bug fix --- .../api/twitter/impl/v1/LocationV1.java | 23 ++++-- .../backend/api/twitter/impl/v1/TweetV1.java | 1 + .../backend/api/twitter/impl/v2/TweetV2.java | 13 ++-- .../twidda/database/AppDatabase.java | 63 ++++++++++++++-- .../twidda/database/DatabaseAdapter.java | 75 ++++++++++++++++--- .../twidda/database/GlobalSettings.java | 18 ++++- .../twidda/database/impl/LocationImpl.java | 54 +++++++------ .../twidda/database/impl/StatusImpl.java | 23 +++++- .../twidda/database/impl/UserImpl.java | 6 +- 9 files changed, 214 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/LocationV1.java b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/LocationV1.java index 60dc2ec8..185a5823 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/LocationV1.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/LocationV1.java @@ -24,7 +24,7 @@ public class LocationV1 implements Location { */ private static final String LOCATION_TYPE = "Point"; - private int woeid; + private long id; private String country; private String place; private String fullName; @@ -35,11 +35,22 @@ public class LocationV1 implements Location { */ public LocationV1(JSONObject json) throws JSONException { JSONObject coordinateJson = json.optJSONObject("coordinates"); - woeid = json.optInt("woeid", 1); + String idStr = json.optString("id"); + int woeId = json.optInt("woeid", 0); place = json.optString("name", ""); fullName = json.optString("full_name", ""); country = json.optString("country", ""); - + // parse ID if any + if (!idStr.isEmpty()) { + try { + id = Long.parseUnsignedLong(idStr, 16); + } catch (NumberFormatException e) { + throw new JSONException("Bad ID:" + idStr); + } + } else { + id = woeId; + } + // add coordinates if (coordinateJson != null) { if (LOCATION_TYPE.equals(coordinateJson.optString("type"))) { JSONArray coordinateArray = coordinateJson.optJSONArray("coordinates"); @@ -55,7 +66,7 @@ public class LocationV1 implements Location { @Override public long getId() { - return woeid; + return id; } @@ -91,13 +102,13 @@ public class LocationV1 implements Location { public boolean equals(@Nullable Object obj) { if (!(obj instanceof Location)) return false; - return ((Location) obj).getId() == woeid; + return ((Location) obj).getId() == id; } @NonNull @Override public String toString() { - return "id=" + woeid + " name=\"" + getFullName() + "\""; + return "id=" + id + " name=\"" + getFullName() + "\""; } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TweetV1.java b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TweetV1.java index edf547c2..15b9c142 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TweetV1.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TweetV1.java @@ -256,6 +256,7 @@ public class TweetV1 implements Status { @Override + @Nullable public Location getLocation() { return location; } diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TweetV2.java b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TweetV2.java index 1d5921d8..d9ce8117 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TweetV2.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TweetV2.java @@ -355,12 +355,6 @@ public class TweetV2 implements Status { } - @Override - public Location getLocation() { - return location; - } - - @NonNull @Override public Card[] getCards() { @@ -368,6 +362,13 @@ public class TweetV2 implements Status { } + @Override + @Nullable + public Location getLocation() { + return location; + } + + @Nullable @Override public Poll getPoll() { diff --git a/app/src/main/java/org/nuclearfog/twidda/database/AppDatabase.java b/app/src/main/java/org/nuclearfog/twidda/database/AppDatabase.java index 933135cb..590b9984 100644 --- a/app/src/main/java/org/nuclearfog/twidda/database/AppDatabase.java +++ b/app/src/main/java/org/nuclearfog/twidda/database/AppDatabase.java @@ -3,6 +3,7 @@ package org.nuclearfog.twidda.database; import static android.database.sqlite.SQLiteDatabase.CONFLICT_IGNORE; import static android.database.sqlite.SQLiteDatabase.CONFLICT_REPLACE; import static org.nuclearfog.twidda.database.DatabaseAdapter.FavoriteTable; +import static org.nuclearfog.twidda.database.DatabaseAdapter.LocationTable; import static org.nuclearfog.twidda.database.DatabaseAdapter.MediaTable; import static org.nuclearfog.twidda.database.DatabaseAdapter.MessageTable; import static org.nuclearfog.twidda.database.DatabaseAdapter.NotificationTable; @@ -20,6 +21,7 @@ import android.database.sqlite.SQLiteDatabase; import androidx.annotation.Nullable; import org.nuclearfog.twidda.backend.lists.Messages; +import org.nuclearfog.twidda.database.impl.LocationImpl; import org.nuclearfog.twidda.database.impl.MediaImpl; import org.nuclearfog.twidda.database.impl.MessageImpl; import org.nuclearfog.twidda.database.impl.NotificationImpl; @@ -27,6 +29,7 @@ import org.nuclearfog.twidda.database.impl.StatusImpl; import org.nuclearfog.twidda.database.impl.TrendImpl; import org.nuclearfog.twidda.database.impl.UserImpl; import org.nuclearfog.twidda.model.Account; +import org.nuclearfog.twidda.model.Location; import org.nuclearfog.twidda.model.Media; import org.nuclearfog.twidda.model.Message; import org.nuclearfog.twidda.model.Notification; @@ -253,6 +256,11 @@ public class AppDatabase { */ private static final String MEDIA_SELECT = MediaTable.KEY + "=?"; + /** + * selection to get location + */ + private static final String LOCATION_SELECT = LocationTable.ID + "=?"; + /** * selection to get user register */ @@ -792,6 +800,12 @@ public class AppDatabase { result.addMedia(mediaList.toArray(new Media[0])); } } + if (result.getLocationId() != 0L) { + Location location = getLocation(db, result.getLocationId()); + if (location != null) { + result.addLocation(location); + } + } return result; } @@ -799,7 +813,7 @@ public class AppDatabase { * get status/message media * * @param key media key - * @param db database instance + * @param db database read instance * @return media item or null */ @Nullable @@ -813,6 +827,24 @@ public class AppDatabase { return result; } + /** + * get status/message location + * + * @param db database read instance + * @param id location ID + * @return location item or null + */ + @Nullable + private Location getLocation(SQLiteDatabase db, long id) { + String[] args = {Long.toString(id)}; + Cursor c = db.query(LocationTable.NAME, LocationImpl.PROJECTION, LOCATION_SELECT, args, null, null, null, SINGLE_ITEM); + Location result = null; + if (c.moveToFirst()) + result = new LocationImpl(c); + c.close(); + return result; + } + /** * get register of a status or zero if status not found * @@ -925,7 +957,7 @@ public class AppDatabase { } else { statusFlags &= ~MEDIA_SENS_MASK; } - ContentValues statusUpdate = new ContentValues(17); + ContentValues statusUpdate = new ContentValues(15); statusUpdate.put(StatusTable.ID, status.getId()); statusUpdate.put(StatusTable.USER, user.getId()); statusUpdate.put(StatusTable.TIMESTAMP, status.getTimestamp()); @@ -939,9 +971,11 @@ public class AppDatabase { statusUpdate.put(StatusTable.REPLYUSER, status.getRepliedUserId()); statusUpdate.put(StatusTable.REPLYNAME, status.getReplyName()); statusUpdate.put(StatusTable.CONVERSATION, status.getConversationId()); - if (status.getLocation() != null) { - statusUpdate.put(StatusTable.PLACE, status.getLocation().getPlace()); - statusUpdate.put(StatusTable.COORDINATE, status.getLocation().getCoordinates()); + if (status.getLocation() != null && status.getLocation().getId() != 0L) { + statusUpdate.put(StatusTable.LOCATION, status.getLocation().getId()); + saveLocation(status.getLocation(), db); + } else { + statusUpdate.put(StatusTable.LOCATION, 0L); } if (status.getMedia().length > 0) { StringBuilder mediaBuf = new StringBuilder(); @@ -961,6 +995,7 @@ public class AppDatabase { * save media information * * @param medias media to save + * @param db database write instance */ private void saveMedia(Media[] medias, SQLiteDatabase db) { for (Media media : medias) { @@ -969,10 +1004,26 @@ public class AppDatabase { mediaColumn.put(MediaTable.URL, media.getUrl()); mediaColumn.put(MediaTable.PREVIEW, media.getPreviewUrl()); mediaColumn.put(MediaTable.TYPE, media.getMediaType()); - db.insertWithOnConflict(MediaTable.NAME, "", mediaColumn, CONFLICT_REPLACE); + db.insertWithOnConflict(MediaTable.NAME, "", mediaColumn, CONFLICT_IGNORE); } } + /** + * save location information + * + * @param location location information to save + * @param db database write instance + */ + private void saveLocation(Location location, SQLiteDatabase db) { + ContentValues locationColumn = new ContentValues(4); + locationColumn.put(LocationTable.ID, location.getId()); + locationColumn.put(LocationTable.FULLNAME, location.getFullName()); + locationColumn.put(LocationTable.COORDINATES, location.getCoordinates()); + locationColumn.put(LocationTable.COUNTRY, location.getCountry()); + locationColumn.put(LocationTable.PLACE, location.getPlace()); + db.insertWithOnConflict(LocationTable.NAME, "", locationColumn, CONFLICT_IGNORE); + } + /** * set register of a status. Update if an entry exists * diff --git a/app/src/main/java/org/nuclearfog/twidda/database/DatabaseAdapter.java b/app/src/main/java/org/nuclearfog/twidda/database/DatabaseAdapter.java index ea89b2ac..8dcf64de 100644 --- a/app/src/main/java/org/nuclearfog/twidda/database/DatabaseAdapter.java +++ b/app/src/main/java/org/nuclearfog/twidda/database/DatabaseAdapter.java @@ -20,7 +20,7 @@ public class DatabaseAdapter { /** * database version */ - private static final int DB_VERSION = 10; + private static final int DB_VERSION = 11; /** * database file name @@ -65,8 +65,7 @@ public class DatabaseAdapter { + StatusTable.REPLY + " INTEGER," + StatusTable.CONVERSATION + " INTEGER," + StatusTable.SOURCE + " TEXT," - + StatusTable.PLACE + " TEXT," - + StatusTable.COORDINATE + " TEXT," + + StatusTable.LOCATION + " INTEGER," + "FOREIGN KEY(" + StatusTable.USER + ")" + "REFERENCES " + UserTable.NAME + "(" + UserTable.ID + "));"; @@ -172,6 +171,17 @@ public class DatabaseAdapter { + MediaTable.URL + " TEXT," + MediaTable.PREVIEW + " TEXT);"; + /** + * SQL query to create location table + */ + public static final String TABLE_LOCATION = "CREATE TABLE IF NOT EXISTS " + + LocationTable.NAME + "(" + + LocationTable.ID + " INTEGER," + + LocationTable.COUNTRY + " TEXT," + + LocationTable.COORDINATES + " TEXT," + + LocationTable.PLACE + " TEXT," + + LocationTable.FULLNAME + " TEXT);"; + /** * table index for status table */ @@ -225,6 +235,11 @@ public class DatabaseAdapter { */ private static final String UPDATE_ADD_CONVERSATION_ID = "ALTER TABLE " + StatusTable.NAME + " ADD " + StatusTable.CONVERSATION + " INTEGER;"; + /** + * update status table add location ID + */ + private static final String UPDATE_ADD_LOCATION_ID = "ALTER TABLE " + StatusTable.NAME + " ADD " + StatusTable.LOCATION + " INTEGER;"; + /** * singleton instance */ @@ -307,6 +322,7 @@ public class DatabaseAdapter { db.execSQL(TABLE_USER_REGISTER); db.execSQL(TABLE_NOTIFICATION); db.execSQL(TABLE_MEDIA); + db.execSQL(TABLE_LOCATION); // create index if not exist db.execSQL(INDX_STATUS); db.execSQL(INDX_STATUS_REG); @@ -333,8 +349,12 @@ public class DatabaseAdapter { db.execSQL(UPDATE_ADD_BEARER); db.setVersion(9); } - if (db.getVersion() < DB_VERSION) { + if (db.getVersion() < 10) { db.execSQL(UPDATE_ADD_CONVERSATION_ID); + db.setVersion(10); + } + if (db.getVersion() < DB_VERSION) { + db.execSQL(UPDATE_ADD_LOCATION_ID); db.setVersion(DB_VERSION); } } @@ -472,12 +492,7 @@ public class DatabaseAdapter { /** * place name of the status */ - String PLACE = "place"; - - /** - * GPS coordinate of the status - */ - String COORDINATE = "geo"; + String LOCATION = "location_id"; /** * ID of the replied status @@ -535,7 +550,7 @@ public class DatabaseAdapter { String NAME = "trend"; /** - * ID of the trend location + * Location ID of the trend */ String ID = "woeID"; @@ -790,7 +805,7 @@ public class DatabaseAdapter { String KEY = "media_key"; /** - * type of media (image,giv or video) + * type of media {@link org.nuclearfog.twidda.model.Media} */ String TYPE = "media_type"; @@ -804,4 +819,40 @@ public class DatabaseAdapter { */ String PREVIEW = "media_preview_url"; } + + /** + * Table for location information + */ + public interface LocationTable { + + /** + * Table name + */ + String NAME = "location"; + + /** + * locaion ID + */ + String ID = "id"; + + /** + * country name + */ + String COUNTRY = "country"; + + /** + * place name + */ + String PLACE = "place"; + + /** + * place coordinates + */ + String COORDINATES = "coordinates"; + + /** + * full name of the location + */ + String FULLNAME = "full_name"; + } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/database/GlobalSettings.java b/app/src/main/java/org/nuclearfog/twidda/database/GlobalSettings.java index 18e236a0..a1b1f1c1 100644 --- a/app/src/main/java/org/nuclearfog/twidda/database/GlobalSettings.java +++ b/app/src/main/java/org/nuclearfog/twidda/database/GlobalSettings.java @@ -554,7 +554,7 @@ public class GlobalSettings { public Location getTrendLocation() { if (account.getApiType() == Account.API_TWITTER) return location; - return new LocationImpl("", -1); + return new LocationImpl( -1L, ""); } /** @@ -697,13 +697,15 @@ public class GlobalSettings { public void setTwitterAlt(boolean enable) { twitterAlt = enable; Editor edit = settings.edit(); - if (enable) { // fixme add hostname changes also in account instance and database + if (enable) { edit.putString(HOSTNAME, TWITTER_ALT_HOST); } else { edit.putString(HOSTNAME, TWITTER_HOST); } edit.putBoolean(ENABLE_TWITTER_ALT, enable); edit.apply(); + // re initialize login information + initLogin(); } /** @@ -986,9 +988,15 @@ public class GlobalSettings { proxyPass = settings.getString(PROXY_PASS, ""); String place = settings.getString(TREND_LOC, DEFAULT_LOCATION_NAME); int woeId = settings.getInt(TREND_ID, DEFAULT_LOCATION_ID); - location = new LocationImpl(place, woeId); - + location = new LocationImpl(woeId, place); // login informations + initLogin(); + } + + /** + * initialize login information + */ + private void initLogin() { String oauthToken = settings.getString(OAUTH_TOKEN, ""); String oauthSecret = settings.getString(OAUTH_SECRET, ""); String consumerToken = settings.getString(CONSUMER_TOKEN, ""); @@ -997,6 +1005,8 @@ public class GlobalSettings { String hostname = settings.getString(HOSTNAME, TWITTER_HOST); int apiId = settings.getInt(CURRENT_API, Account.API_TWITTER); long userId = settings.getLong(CURRENT_ID, 0); + if (apiId == Account.API_TWITTER && twitterAlt) + hostname = TWITTER_ALT_HOST; account = new AccountImpl(userId, oauthToken, oauthSecret, consumerToken, consumerSecret, bearerToken, hostname, apiId); } diff --git a/app/src/main/java/org/nuclearfog/twidda/database/impl/LocationImpl.java b/app/src/main/java/org/nuclearfog/twidda/database/impl/LocationImpl.java index 653b14e3..b5c0a422 100644 --- a/app/src/main/java/org/nuclearfog/twidda/database/impl/LocationImpl.java +++ b/app/src/main/java/org/nuclearfog/twidda/database/impl/LocationImpl.java @@ -1,8 +1,11 @@ package org.nuclearfog.twidda.database.impl; +import android.database.Cursor; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.nuclearfog.twidda.database.DatabaseAdapter.LocationTable; import org.nuclearfog.twidda.model.Location; /** @@ -14,30 +17,39 @@ public class LocationImpl implements Location { private static final long serialVersionUID = 3719416358210741464L; - private int worldId = -1; - private String name = ""; + /** + * SQL projection + */ + public static final String[] PROJECTION = { + LocationTable.ID, + LocationTable.PLACE, + LocationTable.COUNTRY, + LocationTable.FULLNAME, + LocationTable.COORDINATES + }; + + private long id; + private String name; private String coordinates = ""; + private String country = ""; + private String place = ""; /** * @param name place name - * @param worldId world id + * @param id world id */ - public LocationImpl(String name, int worldId) { + public LocationImpl(long id, String name) { this.name = name; - this.worldId = worldId; + this.id = id; } - /** - * @param name place name - * @param coordinates comma separated gps coordinates - */ - public LocationImpl(String name, String coordinates) { - if (name != null) { - this.name = name; - } - if (coordinates != null) { - this.coordinates = coordinates; - } + + public LocationImpl(Cursor cursor) { + id = cursor.getLong(0); + place = cursor.getString(1); + country = cursor.getString(2); + name = cursor.getString(3); + coordinates = cursor.getString(4); } @@ -49,19 +61,19 @@ public class LocationImpl implements Location { @Override public long getId() { - return worldId; + return id; } @Override public String getCountry() { - return ""; + return country; } @Override public String getPlace() { - return ""; + return place; } @@ -75,13 +87,13 @@ public class LocationImpl implements Location { public boolean equals(@Nullable Object obj) { if (!(obj instanceof Location)) return false; - return ((Location) obj).getId() == worldId; + return ((Location) obj).getId() == id; } @NonNull @Override public String toString() { - return "id=" + worldId + " name=\"" + name + "\""; + return "id=" + id + " name=\"" + name + "\""; } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/database/impl/StatusImpl.java b/app/src/main/java/org/nuclearfog/twidda/database/impl/StatusImpl.java index 236f004e..cfe72295 100644 --- a/app/src/main/java/org/nuclearfog/twidda/database/impl/StatusImpl.java +++ b/app/src/main/java/org/nuclearfog/twidda/database/impl/StatusImpl.java @@ -42,6 +42,7 @@ public class StatusImpl implements Status { private long replyUserId; private long myRepostId; private long conversationId; + private long locationId; private Status embedded; private String[] mediaKeys = {}; private Media[] medias = {}; @@ -75,8 +76,7 @@ public class StatusImpl implements Status { replyName = cursor.getString(cursor.getColumnIndexOrThrow(StatusTable.REPLYNAME)); replyID = cursor.getLong(cursor.getColumnIndexOrThrow(StatusTable.REPLYSTATUS)); source = cursor.getString(cursor.getColumnIndexOrThrow(StatusTable.SOURCE)); - String locationName = cursor.getString(cursor.getColumnIndexOrThrow(StatusTable.PLACE)); - String locationCoordinates = cursor.getString(cursor.getColumnIndexOrThrow(StatusTable.COORDINATE)); + locationId = cursor.getLong(cursor.getColumnIndexOrThrow(StatusTable.LOCATION)); String mediaKeys = cursor.getString(cursor.getColumnIndexOrThrow(StatusTable.MEDIA)); userMentions = StringTools.getUserMentions(text, author.getScreenname()); replyUserId = cursor.getLong(cursor.getColumnIndexOrThrow(StatusTable.REPLYUSER)); @@ -89,8 +89,6 @@ public class StatusImpl implements Status { reposted = (register & REPOST_MASK) != 0; sensitive = (register & MEDIA_SENS_MASK) != 0; isHidden = (register & HIDDEN_MASK) != 0; - if ((locationCoordinates != null && !locationCoordinates.isEmpty()) || (locationName != null && !locationName.isEmpty())) - location = new LocationImpl(locationName, locationCoordinates); if (mediaKeys != null && !mediaKeys.isEmpty()) { this.mediaKeys = MEDIA_SEPARATOR.split(mediaKeys); } @@ -215,6 +213,7 @@ public class StatusImpl implements Status { @Override + @Nullable public Location getLocation() { return location; } @@ -291,6 +290,13 @@ public class StatusImpl implements Status { return mediaKeys; } + /** + * @return location ID + */ + public long getLocationId() { + return locationId; + } + /** * attach status referenced by {@link #embeddedId} * @@ -308,4 +314,13 @@ public class StatusImpl implements Status { public void addMedia(@NonNull Media[] medias) { this.medias = medias; } + + /** + * add location information + * + * @param location location item + */ + public void addLocation(Location location) { + this.location = location; + } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/database/impl/UserImpl.java b/app/src/main/java/org/nuclearfog/twidda/database/impl/UserImpl.java index 97105484..29784e64 100644 --- a/app/src/main/java/org/nuclearfog/twidda/database/impl/UserImpl.java +++ b/app/src/main/java/org/nuclearfog/twidda/database/impl/UserImpl.java @@ -112,9 +112,7 @@ public class UserImpl implements User { @Override public String getOriginalBannerImageUrl() { - if (apiType != Account.API_TWITTER || profileBannerUrl.isEmpty()) - return profileBannerUrl; - return profileBannerUrl + "/1500x500"; + return profileBannerUrl; } @@ -122,6 +120,8 @@ public class UserImpl implements User { public String getBannerImageThumbnailUrl() { if (apiType != Account.API_TWITTER || profileBannerUrl.isEmpty()) return profileBannerUrl; + if (profileBannerUrl.endsWith("/1500x500")) + return profileBannerUrl.substring(0, profileBannerUrl.length() - 9) + "/600x200"; return profileBannerUrl + "/600x200"; }