Merge pull request #2 from p1gp1g/UnifiedPush

Unified push
This commit is contained in:
p1gp1g
2020-12-28 15:17:06 +01:00
committed by GitHub
67 changed files with 1158 additions and 293 deletions

17
.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>android</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@@ -11,8 +11,8 @@ android {
applicationId "com.github.gotify"
minSdkVersion 19
targetSdkVersion 29
versionCode 15
versionName "2.0.12"
versionCode 17
versionName "2.0.14"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}

View File

@@ -15,6 +15,7 @@
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/AppTheme">
<activity
android:name=".init.InitializationActivity"
@@ -45,6 +46,16 @@
android:name=".settings.SettingsActivity"
android:theme="@style/AppTheme.NoActionBar"
android:label="@string/title_activity_settings" />
<activity
android:name=".sharing.ShareActivity"
android:theme="@style/AppTheme.NoActionBar"
android:label="Push message">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<service android:name=".service.WebSocketService" />
<receiver android:enabled="true" android:name=".service.RegisterBroadcastReceiver">
@@ -61,4 +72,4 @@
</receiver>
</application>
</manifest>
</manifest>

View File

@@ -14,7 +14,7 @@ import java.util.List;
import static com.github.gotify.api.Callback.call;
public class MissedMessageUtil {
static final int NO_MESSAGES = 0;
static final long NO_MESSAGES = 0;
private final MessageApi api;
@@ -22,8 +22,8 @@ public class MissedMessageUtil {
this.api = api;
}
public void lastReceivedMessage(Callback.SuccessCallback<Integer> successCallback) {
api.getMessages(1, 0)
public void lastReceivedMessage(Callback.SuccessCallback<Long> successCallback) {
api.getMessages(1, 0L)
.enqueue(
call(
(messages) -> {
@@ -37,11 +37,11 @@ public class MissedMessageUtil {
(e) -> {}));
}
public List<Message> missingMessages(int till) {
public List<Message> missingMessages(long till) {
List<Message> result = new ArrayList<>();
try {
Integer since = null;
Long since = null;
while (true) {
PagedMessages pagedMessages = Api.execute(api.getMessages(10, since));
List<Message> messages = pagedMessages.getMessages();
@@ -61,7 +61,7 @@ public class MissedMessageUtil {
return result;
}
private List<Message> filter(List<Message> messages, int till) {
private List<Message> filter(List<Message> messages, long till) {
List<Message> result = new ArrayList<>();
for (Message message : messages) {

View File

@@ -33,6 +33,10 @@ public class Utils {
Snackbar.make(rootView, message, Snackbar.LENGTH_SHORT).show();
}
public static int longToInt(long value) {
return (int) (value % Integer.MAX_VALUE);
}
public static String dateToRelative(OffsetDateTime data) {
long time = data.toInstant().toEpochMilli();
long now = System.currentTimeMillis();
@@ -96,4 +100,11 @@ public class Utils {
if (str == null) return null;
return new Buffer().writeUtf8(str).inputStream();
}
public static <T> T first(T[] data) {
if (data.length != 1) {
throw new IllegalArgumentException("must be one element");
}
return data[0];
}
}

View File

@@ -1,5 +1,7 @@
package com.github.gotify.messages;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.text.util.Linkify;
import android.view.LayoutInflater;
@@ -8,6 +10,7 @@ import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
@@ -133,6 +136,7 @@ public class ListMessageAdapter extends RecyclerView.Adapter<ListMessageAdapter.
ButterKnife.bind(this, view);
preciseDate = false;
dateTime = null;
enableCopyToClipboard();
}
void switchPreciseDate() {
@@ -157,6 +161,33 @@ public class ListMessageAdapter extends RecyclerView.Adapter<ListMessageAdapter.
}
date.setText(text);
}
private void enableCopyToClipboard() {
super.itemView.setOnLongClickListener(
view -> {
ClipboardManager clipboard =
(ClipboardManager)
view.getContext()
.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip =
ClipData.newPlainText(
"GotifyMessageContent", message.getText().toString());
if (clipboard != null) {
clipboard.setPrimaryClip(clip);
Toast toast =
Toast.makeText(
view.getContext(),
view.getContext()
.getString(
R.string.message_copied_to_clipboard),
Toast.LENGTH_SHORT);
toast.show();
}
return true;
});
}
}
public interface Delete {

View File

@@ -43,7 +43,6 @@ import com.github.gotify.Settings;
import com.github.gotify.Utils;
import com.github.gotify.api.Api;
import com.github.gotify.api.ApiException;
import com.github.gotify.api.CertUtils;
import com.github.gotify.api.ClientFactory;
import com.github.gotify.client.ApiClient;
import com.github.gotify.client.api.ClientApi;
@@ -60,23 +59,20 @@ import com.github.gotify.messages.provider.MessageDeletion;
import com.github.gotify.messages.provider.MessageFacade;
import com.github.gotify.messages.provider.MessageState;
import com.github.gotify.messages.provider.MessageWithImage;
import com.github.gotify.picasso.PicassoDataRequestHandler;
import com.github.gotify.picasso.PicassoHandler;
import com.github.gotify.service.WebSocketService;
import com.github.gotify.settings.SettingsActivity;
import com.github.gotify.sharing.ShareActivity;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import com.squareup.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import static com.github.gotify.Utils.first;
import static java.util.Collections.emptyList;
public class MessagesActivity extends AppCompatActivity
@@ -118,14 +114,12 @@ public class MessagesActivity extends AppCompatActivity
private Settings settings;
protected ApplicationHolder appsHolder;
private int appId = MessageState.ALL_MESSAGES;
private long appId = MessageState.ALL_MESSAGES;
private boolean isLoadMore = false;
private Integer selectAppIdOnDrawerClose = null;
private Long selectAppIdOnDrawerClose = null;
int PICASSO_CACHE_SIZE = 50 * 1024 * 1024; // 50 MB
private Cache picassoCache;
private Picasso picasso;
private PicassoHandler picassoHandler;
// we need to keep the target references otherwise they get gc'ed before they can be called.
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@@ -139,8 +133,7 @@ public class MessagesActivity extends AppCompatActivity
Log.i("Entering " + getClass().getSimpleName());
settings = new Settings(this);
picassoCache = new Cache(new File(getCacheDir(), "picasso-cache"), PICASSO_CACHE_SIZE);
picasso = makePicasso();
picassoHandler = new PicassoHandler(this, settings);
client =
ClientFactory.clientToken(settings.url(), settings.sslSettings(), settings.token());
@@ -157,7 +150,7 @@ public class MessagesActivity extends AppCompatActivity
messagesView.getContext(), layoutManager.getOrientation());
ListMessageAdapter adapter =
new ListMessageAdapter(
this, settings, picasso, emptyList(), this::scheduleDeletion);
this, settings, picassoHandler.get(), emptyList(), this::scheduleDeletion);
messagesView.addItemDecoration(dividerItemDecoration);
messagesView.setHasFixedSize(true);
@@ -200,7 +193,7 @@ public class MessagesActivity extends AppCompatActivity
public void onRefreshAll(View view) {
try {
picassoCache.evictAll();
picassoHandler.evict();
} catch (IOException e) {
Log.e("Problem evicting Picasso cache", e);
}
@@ -229,12 +222,15 @@ public class MessagesActivity extends AppCompatActivity
menu.removeGroup(R.id.apps);
targetReferences.clear();
updateMessagesAndStopLoading(messages.get(appId));
for (Application app : applications) {
MenuItem item = menu.add(R.id.apps, app.getId(), APPLICATION_ORDER, app.getName());
for (int i = 0; i < applications.size(); i++) {
Application app = applications.get(i);
MenuItem item = menu.add(R.id.apps, i, APPLICATION_ORDER, app.getName());
item.setCheckable(true);
Target t = Utils.toDrawable(getResources(), item::setIcon);
targetReferences.add(t);
picasso.load(Utils.resolveAbsoluteUrl(settings.url() + "/", app.getImage()))
picassoHandler
.get()
.load(Utils.resolveAbsoluteUrl(settings.url() + "/", app.getImage()))
.error(R.drawable.ic_alarm)
.placeholder(R.drawable.ic_placeholder)
.resize(100, 100)
@@ -242,20 +238,6 @@ public class MessagesActivity extends AppCompatActivity
}
}
private Picasso makePicasso() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.cache(picassoCache);
CertUtils.applySslSettings(builder, settings.sslSettings());
OkHttp3Downloader downloader = new OkHttp3Downloader(builder.build());
return new Picasso.Builder(this)
.addRequestHandler(new PicassoDataRequestHandler())
.downloader(downloader)
.build();
}
private void initDrawer() {
setSupportActionBar(toolbar);
navigationView.setItemIconTintList(null);
@@ -303,7 +285,8 @@ public class MessagesActivity extends AppCompatActivity
int id = item.getItemId();
if (item.getGroupId() == R.id.apps) {
selectAppIdOnDrawerClose = id;
Application app = appsHolder.get().get(id);
selectAppIdOnDrawerClose = app != null ? app.getId() : MessageState.ALL_MESSAGES;
startLoading();
toolbar.setSubtitle(item.getTitle());
} else if (id == R.id.nav_all_messages) {
@@ -321,6 +304,9 @@ public class MessagesActivity extends AppCompatActivity
startActivity(new Intent(this, LogsActivity.class));
} else if (id == R.id.settings) {
startActivity(new Intent(this, SettingsActivity.class));
} else if (id == R.id.push_message) {
Intent intent = new Intent(MessagesActivity.this, ShareActivity.class);
startActivity(intent);
}
drawer.closeDrawer(GravityCompat.START);
@@ -330,7 +316,6 @@ public class MessagesActivity extends AppCompatActivity
public void doLogout(DialogInterface dialog, int which) {
setContentView(R.layout.splash);
new DeleteClientAndNavigateToLogin().execute();
finish();
}
private void startLoading() {
@@ -355,10 +340,17 @@ public class MessagesActivity extends AppCompatActivity
filter.addAction(WebSocketService.NEW_MESSAGE_BROADCAST);
registerReceiver(receiver, filter);
new UpdateMissedMessages().execute(messages.getLastReceivedMessage());
navigationView
.getMenu()
.findItem(appId == MessageState.ALL_MESSAGES ? R.id.nav_all_messages : appId)
.setChecked(true);
int selectedIndex = R.id.nav_all_messages;
if (appId != MessageState.ALL_MESSAGES) {
for (int i = 0; i < appsHolder.get().size(); i++) {
if (appsHolder.get().get(i).getId() == appId) {
selectedIndex = i;
}
}
}
navigationView.getMenu().findItem(selectedIndex).setChecked(true);
super.onResume();
}
@@ -371,7 +363,7 @@ public class MessagesActivity extends AppCompatActivity
@Override
protected void onDestroy() {
super.onDestroy();
picasso.shutdown();
picassoHandler.get().shutdown();
}
private void scheduleDeletion(int position, Message message, boolean listAnimation) {
@@ -542,10 +534,10 @@ public class MessagesActivity extends AppCompatActivity
}
}
private class UpdateMissedMessages extends AsyncTask<Integer, Void, Boolean> {
private class UpdateMissedMessages extends AsyncTask<Long, Void, Boolean> {
@Override
protected Boolean doInBackground(Integer... ids) {
Integer id = first(ids);
protected Boolean doInBackground(Long... ids) {
Long id = first(ids);
if (id == -1) {
return false;
}
@@ -579,10 +571,10 @@ public class MessagesActivity extends AppCompatActivity
return super.onContextItemSelected(item);
}
private class LoadMore extends AsyncTask<Integer, Void, List<MessageWithImage>> {
private class LoadMore extends AsyncTask<Long, Void, List<MessageWithImage>> {
@Override
protected List<MessageWithImage> doInBackground(Integer... appId) {
protected List<MessageWithImage> doInBackground(Long... appId) {
return messages.loadMore(first(appId));
}
@@ -592,7 +584,7 @@ public class MessagesActivity extends AppCompatActivity
}
}
private class SelectApplicationAndUpdateMessages extends AsyncTask<Integer, Void, Integer> {
private class SelectApplicationAndUpdateMessages extends AsyncTask<Long, Void, Long> {
private SelectApplicationAndUpdateMessages(boolean withLoadingSpinner) {
if (withLoadingSpinner) {
@@ -601,14 +593,14 @@ public class MessagesActivity extends AppCompatActivity
}
@Override
protected Integer doInBackground(Integer... appIds) {
Integer appId = first(appIds);
protected Long doInBackground(Long... appIds) {
Long appId = first(appIds);
messages.loadMoreIfNotPresent(appId);
return appId;
}
@Override
protected void onPostExecute(Integer appId) {
protected void onPostExecute(Long appId) {
updateMessagesAndStopLoading(messages.get(appId));
}
}
@@ -641,14 +633,14 @@ public class MessagesActivity extends AppCompatActivity
}
}
private class DeleteMessages extends AsyncTask<Integer, Void, Boolean> {
private class DeleteMessages extends AsyncTask<Long, Void, Boolean> {
DeleteMessages() {
startLoading();
}
@Override
protected Boolean doInBackground(Integer... appId) {
protected Boolean doInBackground(Long... appId) {
return messages.deleteAll(first(appId));
}
@@ -683,7 +675,7 @@ public class MessagesActivity extends AppCompatActivity
if (currentClient != null) {
Log.i("Delete client with id " + currentClient.getId());
api.deleteClient(currentClient.getId());
Api.execute(api.deleteClient(currentClient.getId()));
} else {
Log.e("Could not delete client, client does not exist.");
}
@@ -717,12 +709,4 @@ public class MessagesActivity extends AppCompatActivity
adapter.setItems(messageWithImages);
adapter.notifyDataSetChanged();
}
private <T> T first(T[] data) {
if (data.length != 1) {
throw new IllegalArgumentException("must be one element");
}
return data[0];
}
}

View File

@@ -18,7 +18,7 @@ public class MessageFacade {
this.state = new MessageStateHolder();
}
public synchronized List<MessageWithImage> get(Integer appId) {
public synchronized List<MessageWithImage> get(long appId) {
return combiner.combine(state.state(appId).messages, applicationHolder.get());
}
@@ -28,7 +28,7 @@ public class MessageFacade {
}
}
public synchronized List<MessageWithImage> loadMore(Integer appId) {
public synchronized List<MessageWithImage> loadMore(long appId) {
MessageState state = this.state.state(appId);
if (state.hasNext || !state.loaded) {
PagedMessages pagedMessages = requester.loadMore(state);
@@ -37,7 +37,7 @@ public class MessageFacade {
return get(appId);
}
public synchronized void loadMoreIfNotPresent(Integer appId) {
public synchronized void loadMoreIfNotPresent(long appId) {
MessageState state = this.state.state(appId);
if (!state.loaded) {
loadMore(appId);
@@ -48,7 +48,7 @@ public class MessageFacade {
this.state.clear();
}
public int getLastReceivedMessage() {
public long getLastReceivedMessage() {
return state.getLastReceivedMessage();
}
@@ -70,13 +70,13 @@ public class MessageFacade {
return this.state.undoPendingDeletion();
}
public synchronized boolean deleteAll(Integer appId) {
public synchronized boolean deleteAll(long appId) {
boolean success = this.requester.deleteAll(appId);
this.state.deleteAll(appId);
return success;
}
public synchronized boolean canLoadMore(Integer appId) {
public synchronized boolean canLoadMore(long appId) {
return state.state(appId).hasNext;
}
}

View File

@@ -3,14 +3,14 @@ package com.github.gotify.messages.provider;
import com.github.gotify.client.model.Application;
import com.github.gotify.client.model.Message;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
class MessageImageCombiner {
public class MessageImageCombiner {
List<MessageWithImage> combine(List<Message> messages, List<Application> applications) {
Map<Integer, String> appIdToImage = appIdToImage(applications);
Map<Long, String> appIdToImage = appIdToImage(applications);
List<MessageWithImage> result = new ArrayList<>();
@@ -26,8 +26,8 @@ class MessageImageCombiner {
return result;
}
private Map<Integer, String> appIdToImage(List<Application> applications) {
Map<Integer, String> map = new HashMap<>();
public static Map<Long, String> appIdToImage(List<Application> applications) {
Map<Long, String> map = new ConcurrentHashMap<>();
for (Application app : applications) {
map.put(app.getId(), app.getImage());
}

View File

@@ -35,7 +35,7 @@ class MessageRequester {
messageApi.deleteMessage(message.getId()).enqueue(Callback.call());
}
boolean deleteAll(Integer appId) {
boolean deleteAll(Long appId) {
try {
Log.i("Deleting all messages for " + appId);
if (MessageState.ALL_MESSAGES == appId) {

View File

@@ -5,11 +5,11 @@ import java.util.ArrayList;
import java.util.List;
public class MessageState {
public static final int ALL_MESSAGES = -1;
public static final long ALL_MESSAGES = -1;
int appId;
long appId;
boolean loaded;
boolean hasNext;
int nextSince = 0;
long nextSince = 0;
List<Message> messages = new ArrayList<>();
}

View File

@@ -6,8 +6,8 @@ import java.util.HashMap;
import java.util.Map;
class MessageStateHolder {
private int lastReceivedMessage = -1;
private Map<Integer, MessageState> states = new HashMap<>();
private long lastReceivedMessage = -1;
private Map<Long, MessageState> states = new HashMap<>();
private MessageDeletion pendingDeletion = null;
@@ -15,7 +15,7 @@ class MessageStateHolder {
states = new HashMap<>();
}
synchronized void newMessages(Integer appId, PagedMessages pagedMessages) {
synchronized void newMessages(Long appId, PagedMessages pagedMessages) {
MessageState state = state(appId);
if (!state.loaded && pagedMessages.getMessages().size() > 0) {
@@ -49,7 +49,7 @@ class MessageStateHolder {
if (deletion != null) deleteMessage(deletion.getMessage());
}
synchronized MessageState state(Integer appId) {
synchronized MessageState state(Long appId) {
MessageState state = states.get(appId);
if (state == null) {
return emptyState(appId);
@@ -57,14 +57,14 @@ class MessageStateHolder {
return state;
}
synchronized void deleteAll(Integer appId) {
synchronized void deleteAll(Long appId) {
clear();
MessageState state = state(appId);
state.loaded = true;
states.put(appId, state);
}
private MessageState emptyState(Integer appId) {
private MessageState emptyState(Long appId) {
MessageState emptyState = new MessageState();
emptyState.loaded = false;
emptyState.hasNext = false;
@@ -73,7 +73,7 @@ class MessageStateHolder {
return emptyState;
}
synchronized int getLastReceivedMessage() {
synchronized long getLastReceivedMessage() {
return lastReceivedMessage;
}

View File

@@ -0,0 +1,94 @@
package com.github.gotify.picasso;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.github.gotify.R;
import com.github.gotify.Settings;
import com.github.gotify.Utils;
import com.github.gotify.api.Callback;
import com.github.gotify.api.CertUtils;
import com.github.gotify.api.ClientFactory;
import com.github.gotify.client.api.ApplicationApi;
import com.github.gotify.log.Log;
import com.github.gotify.messages.provider.MessageImageCombiner;
import com.squareup.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
public class PicassoHandler {
private static final int PICASSO_CACHE_SIZE = 50 * 1024 * 1024; // 50 MB
private static final String PICASSO_CACHE_SUBFOLDER = "picasso-cache";
private Context context;
private Settings settings;
private Cache picassoCache;
private Picasso picasso;
private Map<Long, String> appIdToAppImage = new ConcurrentHashMap<>();
public PicassoHandler(Context context, Settings settings) {
this.context = context;
this.settings = settings;
picassoCache =
new Cache(
new File(context.getCacheDir(), PICASSO_CACHE_SUBFOLDER),
PICASSO_CACHE_SIZE);
picasso = makePicasso();
}
private Picasso makePicasso() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.cache(picassoCache);
CertUtils.applySslSettings(builder, settings.sslSettings());
OkHttp3Downloader downloader = new OkHttp3Downloader(builder.build());
return new Picasso.Builder(context).downloader(downloader).build();
}
public Bitmap getIcon(Long appId) {
if (appId == -1) {
return BitmapFactory.decodeResource(context.getResources(), R.drawable.gotify);
}
try {
return picasso.load(
Utils.resolveAbsoluteUrl(
settings.url() + "/", appIdToAppImage.get(appId)))
.get();
} catch (IOException e) {
Log.e("Could not load image for notification", e);
}
return BitmapFactory.decodeResource(context.getResources(), R.drawable.gotify);
}
public void updateAppIds() {
ClientFactory.clientToken(settings.url(), settings.sslSettings(), settings.token())
.createService(ApplicationApi.class)
.getApps()
.enqueue(
Callback.call(
(apps) -> {
appIdToAppImage.clear();
appIdToAppImage.putAll(MessageImageCombiner.appIdToImage(apps));
},
(t) -> {
appIdToAppImage.clear();
}));
}
public Picasso get() {
return picasso;
}
public void evict() throws IOException {
picassoCache.evictAll();
}
}

View File

@@ -29,7 +29,7 @@ class MessagingDatabase(context: Context) : SQLiteOpenHelper(context, DB_NAME, n
throw IllegalStateException("Upgrades not supported")
}
fun registerApp(packageName: String, appId :Int, gotify_token: String, connector_token: String){
fun registerApp(packageName: String, appId :Long, gotify_token: String, connector_token: String){
val db = writableDatabase
val values = ContentValues().apply {
put(FIELD_PACKAGE_NAME, packageName)
@@ -88,7 +88,7 @@ class MessagingDatabase(context: Context) : SQLiteOpenHelper(context, DB_NAME, n
}
}
fun getAppFromId(appId: Int): String{
fun getAppFromId(appId: Long): String{
val db = readableDatabase
val projection = arrayOf(FIELD_PACKAGE_NAME)
val selection = "$FIELD_APP_ID = ?"
@@ -106,7 +106,7 @@ class MessagingDatabase(context: Context) : SQLiteOpenHelper(context, DB_NAME, n
}
}
fun getAppId(packageName: String): Int{
fun getAppId(packageName: String): Long{
val db = readableDatabase
val projection = arrayOf(FIELD_APP_ID)
val selection = "$FIELD_PACKAGE_NAME = ?"
@@ -120,7 +120,7 @@ class MessagingDatabase(context: Context) : SQLiteOpenHelper(context, DB_NAME, n
null,
null
).use { cursor ->
if (cursor.moveToFirst()) cursor.getInt(cursor.getColumnIndex(FIELD_APP_ID)) else -1
if (cursor.moveToFirst()) cursor.getLong(cursor.getColumnIndex(FIELD_APP_ID)) else -1
}
}

View File

@@ -1,7 +1,9 @@
package com.github.gotify.service;
import android.app.AlarmManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Handler;
import com.github.gotify.SSLSettings;
import com.github.gotify.Utils;
@@ -9,7 +11,9 @@ import com.github.gotify.api.Callback;
import com.github.gotify.api.CertUtils;
import com.github.gotify.client.model.Message;
import com.github.gotify.log.Log;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@@ -17,8 +21,10 @@ import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
public class WebSocketConnection {
class WebSocketConnection {
private static final AtomicLong ID = new AtomicLong(0);
private final ConnectivityManager connectivityManager;
private final AlarmManager alarmManager;
private OkHttpClient client;
private final Handler reconnectHandler = new Handler();
@@ -34,15 +40,17 @@ public class WebSocketConnection {
private BadRequestRunnable onBadRequest;
private OnNetworkFailureRunnable onNetworkFailure;
private Runnable onReconnected;
private boolean isClosed;
private State state;
private Runnable onDisconnect;
WebSocketConnection(
String baseUrl,
SSLSettings settings,
String token,
ConnectivityManager connectivityManager) {
ConnectivityManager connectivityManager,
AlarmManager alarmManager) {
this.connectivityManager = connectivityManager;
this.alarmManager = alarmManager;
OkHttpClient.Builder builder =
new OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS)
@@ -102,67 +110,97 @@ public class WebSocketConnection {
}
public synchronized WebSocketConnection start() {
if (state == State.Connecting || state == State.Connected) {
return this;
}
close();
isClosed = false;
Log.i("WebSocket: starting...");
state = State.Connecting;
long nextId = ID.incrementAndGet();
Log.i("WebSocket(" + nextId + "): starting...");
webSocket = client.newWebSocket(request(), new Listener());
webSocket = client.newWebSocket(request(), new Listener(nextId));
return this;
}
public synchronized void close() {
if (webSocket != null) {
Log.i("WebSocket: closing existing connection.");
isClosed = true;
Log.i("WebSocket(" + ID.get() + "): closing existing connection.");
state = State.Disconnected;
webSocket.close(1000, "");
webSocket = null;
}
}
public synchronized void scheduleReconnect(long millis) {
reconnectHandler.removeCallbacks(reconnectCallback);
public synchronized void scheduleReconnect(long seconds) {
if (state == State.Connecting || state == State.Connected) {
return;
}
state = State.Scheduled;
Log.i(
"WebSocket: scheduling a restart in "
+ TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS)
+ " second(s)");
reconnectHandler.postDelayed(reconnectCallback, millis);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Log.i(
"WebSocket: scheduling a restart in "
+ seconds
+ " second(s) (via alarm manager)");
final Calendar future = Calendar.getInstance();
future.add(Calendar.SECOND, (int) seconds);
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
future.getTimeInMillis(),
"reconnect-tag",
this::start,
null);
} else {
Log.i("WebSocket: scheduling a restart in " + seconds + " second(s)");
reconnectHandler.removeCallbacks(reconnectCallback);
reconnectHandler.postDelayed(reconnectCallback, TimeUnit.SECONDS.toMillis(seconds));
}
}
private class Listener extends WebSocketListener {
private final long id;
public Listener(long id) {
this.id = id;
}
@Override
public void onOpen(WebSocket webSocket, Response response) {
Log.i("WebSocket: opened");
synchronized (this) {
onOpen.run();
syncExec(
() -> {
state = State.Connected;
Log.i("WebSocket(" + id + "): opened");
onOpen.run();
if (errorCount > 0) {
onReconnected.run();
errorCount = 0;
}
}
if (errorCount > 0) {
onReconnected.run();
errorCount = 0;
}
});
super.onOpen(webSocket, response);
}
@Override
public void onMessage(WebSocket webSocket, String text) {
Log.i("WebSocket: received message " + text);
synchronized (this) {
Message message = Utils.JSON.fromJson(text, Message.class);
onMessage.onSuccess(message);
}
syncExec(
() -> {
Log.i("WebSocket(" + id + "): received message " + text);
Message message = Utils.JSON.fromJson(text, Message.class);
onMessage.onSuccess(message);
});
super.onMessage(webSocket, text);
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
synchronized (this) {
if (!isClosed) {
Log.w("WebSocket: closed");
onClose.run();
}
}
syncExec(
() -> {
if (state == State.Connected) {
Log.w("WebSocket(" + id + "): closed");
onClose.run();
}
state = State.Disconnected;
});
super.onClosed(webSocket, code, reason);
}
@@ -171,31 +209,41 @@ public class WebSocketConnection {
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
String code = response != null ? "StatusCode: " + response.code() : "";
String message = response != null ? response.message() : "";
Log.e("WebSocket: failure " + code + " Message: " + message, t);
synchronized (this) {
if (response != null && response.code() >= 400 && response.code() <= 499) {
onBadRequest.execute(message);
close();
return;
}
Log.e("WebSocket(" + id + "): failure " + code + " Message: " + message, t);
syncExec(
() -> {
state = State.Disconnected;
if (response != null && response.code() >= 400 && response.code() <= 499) {
onBadRequest.execute(message);
close();
return;
}
errorCount++;
errorCount++;
NetworkInfo network = connectivityManager.getActiveNetworkInfo();
if (network == null || !network.isConnected()) {
Log.i("WebSocket: Network not connected");
onDisconnect.run();
return;
}
NetworkInfo network = connectivityManager.getActiveNetworkInfo();
if (network == null || !network.isConnected()) {
Log.i("WebSocket(" + id + "): Network not connected");
onDisconnect.run();
return;
}
int minutes = Math.min(errorCount * 2 - 1, 20);
int minutes = Math.min(errorCount * 2 - 1, 20);
onNetworkFailure.execute(minutes);
scheduleReconnect(TimeUnit.MINUTES.toMillis(minutes));
}
onNetworkFailure.execute(minutes);
scheduleReconnect(TimeUnit.MINUTES.toSeconds(minutes));
});
super.onFailure(webSocket, t, response);
}
private void syncExec(Runnable runnable) {
synchronized (this) {
if (ID.get() == id) {
runnable.run();
}
}
}
}
interface BadRequestRunnable {
@@ -205,4 +253,11 @@ public class WebSocketConnection {
interface OnNetworkFailureRunnable {
void execute(long millis);
}
enum State {
Scheduled,
Connecting,
Connected,
Disconnected
}
}

View File

@@ -1,5 +1,6 @@
package com.github.gotify.service;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -22,40 +23,44 @@ import com.github.gotify.R;
import com.github.gotify.Settings;
import com.github.gotify.Utils;
import com.github.gotify.api.ClientFactory;
import com.github.gotify.client.ApiClient;
import com.github.gotify.client.api.MessageApi;
import com.github.gotify.client.model.Message;
import com.github.gotify.log.Log;
import com.github.gotify.log.UncaughtExceptionHandler;
import com.github.gotify.messages.Extras;
import com.github.gotify.messages.MessagesActivity;
import com.github.gotify.picasso.PicassoHandler;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import static com.github.gotify.api.Callback.call;
public class WebSocketService extends Service {
public static final String NEW_MESSAGE_BROADCAST =
WebSocketService.class.getName() + ".NEW_MESSAGE";
private static final int NOT_LOADED = -2;
private static final long NOT_LOADED = -2;
private Settings settings;
private WebSocketConnection connection;
private AtomicInteger lastReceivedMessage = new AtomicInteger(NOT_LOADED);
private AtomicLong lastReceivedMessage = new AtomicLong(NOT_LOADED);
private MissedMessageUtil missingMessageUtil;
private PicassoHandler picassoHandler;
@Override
public void onCreate() {
super.onCreate();
settings = new Settings(this);
missingMessageUtil =
new MissedMessageUtil(
ClientFactory.clientToken(
settings.url(), settings.sslSettings(), settings.token())
.createService(MessageApi.class));
ApiClient client =
ClientFactory.clientToken(settings.url(), settings.sslSettings(), settings.token());
missingMessageUtil = new MissedMessageUtil(client.createService(MessageApi.class));
Log.i("Create " + getClass().getSimpleName());
picassoHandler = new PicassoHandler(this, settings);
}
@Override
@@ -92,12 +97,17 @@ public class WebSocketService extends Service {
ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
connection =
new WebSocketConnection(
settings.url(), settings.sslSettings(), settings.token(), cm)
settings.url(),
settings.sslSettings(),
settings.token(),
cm,
alarmManager)
.onOpen(this::onOpen)
.onClose(() -> foreground(getString(R.string.websocket_closed)))
.onClose(this::onClose)
.onBadRequest(this::onBadRequest)
.onNetworkFailure(
(min) -> foreground(getString(R.string.websocket_failed, min)))
@@ -110,6 +120,26 @@ public class WebSocketService extends Service {
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
ReconnectListener receiver = new ReconnectListener(this::doReconnect);
registerReceiver(receiver, intentFilter);
picassoHandler.updateAppIds();
}
private void onClose() {
foreground(getString(R.string.websocket_closed_try_reconnect));
ClientFactory.userApiWithToken(settings)
.currentUser()
.enqueue(
call(
(ignored) -> this.doReconnect(),
(exception) -> {
if (exception.code() == 401) {
foreground(getString(R.string.websocket_closed_logout));
} else {
Log.i(
"WebSocket closed but the user still authenticated, trying to reconnect");
this.doReconnect();
}
}));
}
private void onDisconnect() {
@@ -121,7 +151,7 @@ public class WebSocketService extends Service {
return;
}
connection.scheduleReconnect(TimeUnit.SECONDS.toMillis(5));
connection.scheduleReconnect(15);
}
private void onBadRequest(String message) {
@@ -133,7 +163,7 @@ public class WebSocketService extends Service {
}
private void notifyMissedNotifications() {
int messageId = lastReceivedMessage.get();
long messageId = lastReceivedMessage.get();
if (messageId == NOT_LOADED) {
return;
}
@@ -171,6 +201,7 @@ public class WebSocketService extends Service {
if (lastReceivedMessage.get() < message.getId()) {
lastReceivedMessage.set(message.getId());
}
broadcast(message);
try (MessagingDatabase db = new MessagingDatabase(this)) {
String registeredAppName = db.getAppFromId(message.getAppid());
@@ -186,7 +217,8 @@ public class WebSocketService extends Service {
message.getTitle(),
message.getMessage(),
message.getPriority(),
message.getExtras());
message.getExtras(),
message.getAppid());
}
private void broadcast(Message message) {
@@ -228,6 +260,16 @@ public class WebSocketService extends Service {
private void showNotification(
int id, String title, String message, long priority, Map<String, Object> extras) {
showNotification(id, title, message, priority, extras, -1L);
}
private void showNotification(
long id,
String title,
String message,
long priority,
Map<String, Object> extras,
Long appid) {
Intent intent;
@@ -267,6 +309,7 @@ public class WebSocketService extends Service {
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_gotify)
.setLargeIcon(picassoHandler.getIcon(appid))
.setTicker(getString(R.string.app_name) + " - " + title)
.setGroup(NotificationSupport.Group.MESSAGES)
.setContentTitle(title)
@@ -279,7 +322,7 @@ public class WebSocketService extends Service {
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id, b.build());
notificationManager.notify(Utils.longToInt(id), b.build());
}
@RequiresApi(Build.VERSION_CODES.N)

View File

@@ -0,0 +1,153 @@
package com.github.gotify.sharing;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.github.gotify.R;
import com.github.gotify.Settings;
import com.github.gotify.api.Api;
import com.github.gotify.api.ApiException;
import com.github.gotify.api.ClientFactory;
import com.github.gotify.client.ApiClient;
import com.github.gotify.client.api.MessageApi;
import com.github.gotify.client.model.Application;
import com.github.gotify.client.model.Message;
import com.github.gotify.log.Log;
import com.github.gotify.messages.provider.ApplicationHolder;
import java.util.ArrayList;
import java.util.List;
import static com.github.gotify.Utils.first;
public class ShareActivity extends AppCompatActivity {
private Settings settings;
private ApplicationHolder appsHolder;
@BindView(R.id.title)
EditText edtTxtTitle;
@BindView(R.id.content)
EditText edtTxtContent;
@BindView(R.id.edtTxtPriority)
EditText edtTxtPriority;
@BindView(R.id.appSpinner)
Spinner appSpinner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_share);
ButterKnife.bind(this);
Log.i("Entering " + getClass().getSimpleName());
setSupportActionBar(findViewById(R.id.toolbar));
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowCustomEnabled(true);
}
settings = new Settings(this);
Intent intent = getIntent();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(intent.getAction()) && "text/plain".equals(type)) {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
edtTxtContent.setText(sharedText);
}
}
ApiClient client =
ClientFactory.clientToken(settings.url(), settings.sslSettings(), settings.token());
appsHolder = new ApplicationHolder(this, client);
appsHolder.onUpdate(() -> populateSpinner(appsHolder.get()));
appsHolder.request();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
@OnClick(R.id.push_button)
public void pushMessage(View view) {
String titleText = edtTxtTitle.getText().toString();
String contentText = edtTxtContent.getText().toString();
String priority = edtTxtPriority.getText().toString();
int appIndex = appSpinner.getSelectedItemPosition();
if (contentText.isEmpty()) {
Toast.makeText(this, "Content should not be empty.", Toast.LENGTH_LONG).show();
return;
} else if (priority.isEmpty()) {
Toast.makeText(this, "Priority should be number.", Toast.LENGTH_LONG).show();
return;
}
Message message = new Message();
if (!titleText.isEmpty()) {
message.setTitle(titleText);
}
message.setMessage(contentText);
message.setPriority(Long.parseLong(priority));
new PushMessage(appsHolder.get().get(appIndex).getToken()).execute(message);
}
private void populateSpinner(List<Application> apps) {
List<String> appNameList = new ArrayList<>();
for (Application app : apps) {
appNameList.add(app.getName());
}
ArrayAdapter<String> adapter =
new ArrayAdapter<>(
this, android.R.layout.simple_spinner_dropdown_item, appNameList);
appSpinner.setAdapter(adapter);
}
private class PushMessage extends AsyncTask<Message, String, String> {
private String token;
public PushMessage(String token) {
this.token = token;
}
@Override
protected String doInBackground(Message... messages) {
List<Application> apps = appsHolder.get();
ApiClient pushClient =
ClientFactory.clientToken(settings.url(), settings.sslSettings(), token);
try {
MessageApi messageApi = pushClient.createService(MessageApi.class);
Api.execute(messageApi.createMessage(first(messages)));
return "Pushed!";
} catch (ApiException apiException) {
Log.e("Failed sending message", apiException);
return "Oops! Something went wrong...";
}
}
@Override
protected void onPostExecute(String message) {
Toast.makeText(ShareActivity.this, message, Toast.LENGTH_LONG).show();
ShareActivity.this.finish();
}
}
}

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/icons"
android:pathData="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
</vector>

View File

@@ -1,5 +1,7 @@
<vector android:height="24dp" android:viewportHeight="20"
android:viewportWidth="20" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
android:viewportWidth="20"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="@color/icons"
android:pathData="M15.95,10.78c0.03,-0.25 0.05,-0.51 0.05,-0.78s-0.02,-0.53 -0.06,-0.78l1.69,-1.32c0.15,-0.12 0.19,-0.34 0.1,-0.51l-1.6,-2.77c-0.1,-0.18 -0.31,-0.24 -0.49,-0.18l-1.99,0.8c-0.42,-0.32 -0.86,-0.58 -1.35,-0.78L12,2.34c-0.03,-0.2 -0.2,-0.34 -0.4,-0.34H8.4c-0.2,0 -0.36,0.14 -0.39,0.34l-0.3,2.12c-0.49,0.2 -0.94,0.47 -1.35,0.78l-1.99,-0.8c-0.18,-0.07 -0.39,0 -0.49,0.18l-1.6,2.77c-0.1,0.18 -0.06,0.39 0.1,0.51l1.69,1.32c-0.04,0.25 -0.07,0.52 -0.07,0.78s0.02,0.53 0.06,0.78L2.37,12.1c-0.15,0.12 -0.19,0.34 -0.1,0.51l1.6,2.77c0.1,0.18 0.31,0.24 0.49,0.18l1.99,-0.8c0.42,0.32 0.86,0.58 1.35,0.78l0.3,2.12c0.04,0.2 0.2,0.34 0.4,0.34h3.2c0.2,0 0.37,-0.14 0.39,-0.34l0.3,-2.12c0.49,-0.2 0.94,-0.47 1.35,-0.78l1.99,0.8c0.18,0.07 0.39,0 0.49,-0.18l1.6,-2.77c0.1,-0.18 0.06,-0.39 -0.1,-0.51l-1.67,-1.32zM10,13c-1.65,0 -3,-1.35 -3,-3s1.35,-3 3,-3 3,1.35 3,3 -1.35,3 -3,3z"/>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/app_bar_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp">
<EditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/push_title_hint"
android:inputType="text"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/push_content_hint"
android:inputType="textCapSentences|textMultiLine"
android:maxLength="2000"
android:maxLines="10" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edtTxtPriority"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:digits="0123456789"
android:hint="@string/push_priority_hint"
android:imeOptions="actionDone"
android:inputType="numberSigned"
android:maxLength="3"
android:text="0" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp">
<TextView
android:id="@+id/txtAppListDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/appListDescription" />
<Spinner
android:id="@+id/appSpinner"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:spinnerMode="dropdown"
android:textSize="18sp" />
</LinearLayout>
<Button
android:id="@+id/push_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginBottom="20dp"
android:layout_marginHorizontal="20dp"
android:text="@string/push_button" />
</LinearLayout>

View File

@@ -15,6 +15,12 @@
</group>
<group android:checkableBehavior="single">
<item
android:orderInCategory="2"
android:icon="@drawable/ic_send"
android:id="@+id/push_message"
android:title="@string/push_message"
/>
<item
android:icon="@drawable/ic_settings"
android:orderInCategory="2"

View File

@@ -21,7 +21,8 @@
<string name="auth_failed">Server returned 401 unauthorized while trying to get current user. This can be caused by deleting the client for this session.</string>
<string name="other_error">Could not get current user. Server (%s) responded with code %d: body (first 200 chars): %s</string>
<string name="websocket_failed">Connection failed, trying again in %d minutes</string>
<string name="websocket_closed">WebSocket closed; The client-token could be invalidated, please re-login</string>
<string name="websocket_closed_logout">User action required: Please login, the authentication token isn\'t valid anymore.</string>
<string name="websocket_closed_try_reconnect">Connection closed, trying to establish a new one.</string>
<string name="grouped_message">Received %d messages while being disconnected</string>
<string name="delete_all">Delete all</string>
<string name="delete_logs">Delete logs</string>
@@ -36,7 +37,6 @@
<string name="gotify_url">https://push.example.com</string>
<string name="username">Username</string>
<string name="password">Password</string>
<string name="show_advanced">Show Advanced Options</string>
<string name="disabled_validate_ssl">Disable SSL Validation</string>
<string name="select_ca_certificate">Select CA Certificate</string>
<string name="select_ca_file">Select a Certificate File</string>
@@ -68,4 +68,12 @@
<string name="settings_appearance">Appearance</string>
<string name="setting_theme">Theme</string>
<string name="setting_key_theme">theme</string>
<string name="push_message">Push message</string>
<string name="appListDescription">App:</string>
<string name="priorityDescription">Priority:</string>
<string name="push_button">Push Message</string>
<string name="push_title_hint">Title</string>
<string name="push_content_hint">Content</string>
<string name="push_priority_hint">Priority</string>
<string name="message_copied_to_clipboard">Content copied to clipboard</string>
</resources>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- Trust preinstalled CAs -->
<certificates src="system" />
<!-- Additionally trust user added CAs -->
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>

View File

@@ -8,10 +8,9 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:4.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@@ -70,4 +69,4 @@ dependencies {
swaggerCodegen 'io.swagger:swagger-codegen-cli:2.3.1'
}
generateSwaggerCode.dependsOn downloadSpec
generateSwaggerCode.dependsOn downloadSpec

View File

@@ -10,7 +10,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:4.0.0'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
}
}

View File

@@ -5,7 +5,7 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**description** | **String** | The description of the application. |
**id** | **Integer** | The application id. |
**id** | **Long** | The application id. |
**image** | **String** | The image of the application. |
**internal** | **Boolean** | Whether the application is an internal application. Internal applications should not be deleted. |
**name** | **String** | The application name. This is how the application should be displayed to the user. |

View File

@@ -110,7 +110,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
ApplicationApi apiInstance = new ApplicationApi();
Integer id = 56; // Integer | the application id
Long id = 789L; // Long | the application id
try {
Void result = apiInstance.deleteApp(id);
System.out.println(result);
@@ -124,7 +124,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the application id |
**id** | **Long**| the application id |
### Return type
@@ -235,7 +235,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
ApplicationApi apiInstance = new ApplicationApi();
Application body = new Application(); // Application | the application to update
Integer id = 56; // Integer | the application id
Long id = 789L; // Long | the application id
try {
Application result = apiInstance.updateApplication(body, id);
System.out.println(result);
@@ -250,7 +250,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**Application**](Application.md)| the application to update |
**id** | **Integer**| the application id |
**id** | **Long**| the application id |
### Return type
@@ -301,7 +301,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
ApplicationApi apiInstance = new ApplicationApi();
File file = new File("/path/to/file.txt"); // File | the application image
Integer id = 56; // Integer | the application id
Long id = 789L; // Long | the application id
try {
Application result = apiInstance.uploadAppImage(file, id);
System.out.println(result);
@@ -316,7 +316,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**file** | **File**| the application image |
**id** | **Integer**| the application id |
**id** | **Long**| the application id |
### Return type

View File

@@ -4,7 +4,7 @@
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **Integer** | The client id. |
**id** | **Long** | The client id. |
**name** | **String** | The client name. This is how the client should be displayed to the user. |
**token** | **String** | The client token. Can be used as &#x60;clientToken&#x60;. See Authentication. |

View File

@@ -7,6 +7,7 @@ Method | HTTP request | Description
[**createClient**](ClientApi.md#createClient) | **POST** client | Create a client.
[**deleteClient**](ClientApi.md#deleteClient) | **DELETE** client/{id} | Delete a client.
[**getClients**](ClientApi.md#getClients) | **GET** client | Return all clients.
[**updateClient**](ClientApi.md#updateClient) | **PUT** client/{id} | Update a client.
<a name="createClient"></a>
@@ -108,7 +109,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
ClientApi apiInstance = new ClientApi();
Integer id = 56; // Integer | the client id
Long id = 789L; // Long | the client id
try {
Void result = apiInstance.deleteClient(id);
System.out.println(result);
@@ -122,7 +123,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the client id |
**id** | **Long**| the client id |
### Return type
@@ -197,3 +198,69 @@ This endpoint does not need any parameter.
- **Content-Type**: application/json
- **Accept**: application/json
<a name="updateClient"></a>
# **updateClient**
> Client updateClient(body, id)
Update a client.
### Example
```java
// Import classes:
//import com.github.gotify.client.ApiClient;
//import com.github.gotify.client.ApiException;
//import com.github.gotify.client.Configuration;
//import com.github.gotify.client.auth.*;
//import com.github.gotify.client.api.ClientApi;
ApiClient defaultClient = Configuration.getDefaultApiClient();
// Configure HTTP basic authorization: basicAuth
HttpBasicAuth basicAuth = (HttpBasicAuth) defaultClient.getAuthentication("basicAuth");
basicAuth.setUsername("YOUR USERNAME");
basicAuth.setPassword("YOUR PASSWORD");
// Configure API key authorization: clientTokenHeader
ApiKeyAuth clientTokenHeader = (ApiKeyAuth) defaultClient.getAuthentication("clientTokenHeader");
clientTokenHeader.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//clientTokenHeader.setApiKeyPrefix("Token");
// Configure API key authorization: clientTokenQuery
ApiKeyAuth clientTokenQuery = (ApiKeyAuth) defaultClient.getAuthentication("clientTokenQuery");
clientTokenQuery.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//clientTokenQuery.setApiKeyPrefix("Token");
ClientApi apiInstance = new ClientApi();
Client body = new Client(); // Client | the client to update
Long id = 789L; // Long | the client id
try {
Client result = apiInstance.updateClient(body, id);
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling ClientApi#updateClient");
e.printStackTrace();
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**Client**](Client.md)| the client to update |
**id** | **Long**| the client id |
### Return type
[**Client**](Client.md)
### Authorization
[basicAuth](../README.md#basicAuth), [clientTokenHeader](../README.md#clientTokenHeader), [clientTokenQuery](../README.md#clientTokenQuery)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json

11
client/docs/Health.md Normal file
View File

@@ -0,0 +1,11 @@
# Health
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**database** | **String** | The health of the database connection. |
**health** | **String** | The health of the overall application. |

48
client/docs/HealthApi.md Normal file
View File

@@ -0,0 +1,48 @@
# HealthApi
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**getHealth**](HealthApi.md#getHealth) | **GET** health | Get health information.
<a name="getHealth"></a>
# **getHealth**
> Health getHealth()
Get health information.
### Example
```java
// Import classes:
//import com.github.gotify.client.ApiException;
//import com.github.gotify.client.api.HealthApi;
HealthApi apiInstance = new HealthApi();
try {
Health result = apiInstance.getHealth();
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling HealthApi#getHealth");
e.printStackTrace();
}
```
### Parameters
This endpoint does not need any parameter.
### Return type
[**Health**](Health.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json

View File

@@ -4,11 +4,11 @@
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**appid** | **Integer** | The application id that send this message. |
**appid** | **Long** | The application id that send this message. |
**date** | [**OffsetDateTime**](OffsetDateTime.md) | The date the message was created. |
**extras** | **Map&lt;String, Object&gt;** | The extra data sent along the message. The extra fields are stored in a key-value scheme. Only accepted in CreateMessage requests with application/json content-type. The keys should be in the following format: &amp;lt;top-namespace&amp;gt;::[&amp;lt;sub-namespace&amp;gt;::]&amp;lt;action&amp;gt; These namespaces are reserved and might be used in the official clients: gotify android ios web server client. Do not use them for other purposes. | [optional]
**id** | **Integer** | The message id. |
**message** | **String** | The actual message. |
**id** | **Long** | The message id. |
**message** | **String** | The message. Markdown (excluding html) is allowed. |
**priority** | **Long** | The priority of the message. | [optional]
**title** | **String** | The title of the message. | [optional]

View File

@@ -109,7 +109,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
MessageApi apiInstance = new MessageApi();
Integer id = 56; // Integer | the application id
Long id = 789L; // Long | the application id
try {
Void result = apiInstance.deleteAppMessages(id);
System.out.println(result);
@@ -123,7 +123,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the application id |
**id** | **Long**| the application id |
### Return type
@@ -173,7 +173,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
MessageApi apiInstance = new MessageApi();
Integer id = 56; // Integer | the message id
Long id = 789L; // Long | the message id
try {
Void result = apiInstance.deleteMessage(id);
System.out.println(result);
@@ -187,7 +187,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the message id |
**id** | **Long**| the message id |
### Return type
@@ -297,9 +297,9 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
MessageApi apiInstance = new MessageApi();
Integer id = 56; // Integer | the application id
Long id = 789L; // Long | the application id
Integer limit = 100; // Integer | the maximal amount of messages to return
Integer since = 56; // Integer | return all messages with an ID less than this value
Long since = 789L; // Long | return all messages with an ID less than this value
try {
PagedMessages result = apiInstance.getAppMessages(id, limit, since);
System.out.println(result);
@@ -313,9 +313,9 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the application id |
**id** | **Long**| the application id |
**limit** | **Integer**| the maximal amount of messages to return | [optional] [default to 100]
**since** | **Integer**| return all messages with an ID less than this value | [optional]
**since** | **Long**| return all messages with an ID less than this value | [optional]
### Return type
@@ -366,7 +366,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
MessageApi apiInstance = new MessageApi();
Integer limit = 100; // Integer | the maximal amount of messages to return
Integer since = 56; // Integer | return all messages with an ID less than this value
Long since = 789L; // Long | return all messages with an ID less than this value
try {
PagedMessages result = apiInstance.getMessages(limit, since);
System.out.println(result);
@@ -381,7 +381,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**limit** | **Integer**| the maximal amount of messages to return | [optional] [default to 100]
**since** | **Integer**| return all messages with an ID less than this value | [optional]
**since** | **Long**| return all messages with an ID less than this value | [optional]
### Return type

View File

@@ -6,7 +6,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**limit** | **Long** | The limit of the messages for the current request. |
**next** | **String** | The request url for the next page. Empty/Null when no next page is available. | [optional]
**since** | **Integer** | The ID of the last message returned in the current request. Use this as alternative to the next link. |
**since** | **Long** | The ID of the last message returned in the current request. Use this as alternative to the next link. |
**size** | **Long** | The amount of messages that got returned in the current request. |

View File

@@ -47,7 +47,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
PluginApi apiInstance = new PluginApi();
Integer id = 56; // Integer | the plugin id
Long id = 789L; // Long | the plugin id
try {
Void result = apiInstance.disablePlugin(id);
System.out.println(result);
@@ -61,7 +61,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the plugin id |
**id** | **Long**| the plugin id |
### Return type
@@ -111,7 +111,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
PluginApi apiInstance = new PluginApi();
Integer id = 56; // Integer | the plugin id
Long id = 789L; // Long | the plugin id
try {
Void result = apiInstance.enablePlugin(id);
System.out.println(result);
@@ -125,7 +125,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the plugin id |
**id** | **Long**| the plugin id |
### Return type
@@ -175,7 +175,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
PluginApi apiInstance = new PluginApi();
Integer id = 56; // Integer | the plugin id
Long id = 789L; // Long | the plugin id
try {
Object result = apiInstance.getPluginConfig(id);
System.out.println(result);
@@ -189,7 +189,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the plugin id |
**id** | **Long**| the plugin id |
### Return type
@@ -239,7 +239,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
PluginApi apiInstance = new PluginApi();
Integer id = 56; // Integer | the plugin id
Long id = 789L; // Long | the plugin id
try {
String result = apiInstance.getPluginDisplay(id);
System.out.println(result);
@@ -253,7 +253,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the plugin id |
**id** | **Long**| the plugin id |
### Return type
@@ -363,7 +363,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
PluginApi apiInstance = new PluginApi();
Integer id = 56; // Integer | the plugin id
Long id = 789L; // Long | the plugin id
try {
Void result = apiInstance.updatePluginConfig(id);
System.out.println(result);
@@ -377,7 +377,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the plugin id |
**id** | **Long**| the plugin id |
### Return type

View File

@@ -7,7 +7,7 @@ Name | Type | Description | Notes
**author** | **String** | The author of the plugin. | [optional]
**capabilities** | **List&lt;String&gt;** | Capabilities the plugin provides |
**enabled** | **Boolean** | Whether the plugin instance is enabled. |
**id** | **Integer** | The plugin id. |
**id** | **Long** | The plugin id. |
**license** | **String** | The license of the plugin. | [optional]
**modulePath** | **String** | The module path of the plugin. |
**name** | **String** | The plugin name. |

View File

@@ -5,7 +5,7 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**admin** | **Boolean** | If the user is an administrator. | [optional]
**id** | **Integer** | The user id. |
**id** | **Long** | The user id. |
**name** | **String** | The user name. For login. |

View File

@@ -172,7 +172,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
UserApi apiInstance = new UserApi();
Integer id = 56; // Integer | the user id
Long id = 789L; // Long | the user id
try {
Void result = apiInstance.deleteUser(id);
System.out.println(result);
@@ -186,7 +186,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the user id |
**id** | **Long**| the user id |
### Return type
@@ -236,7 +236,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
UserApi apiInstance = new UserApi();
Integer id = 56; // Integer | the user id
Long id = 789L; // Long | the user id
try {
User result = apiInstance.getUser(id);
System.out.println(result);
@@ -250,7 +250,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the user id |
**id** | **Long**| the user id |
### Return type
@@ -424,7 +424,7 @@ clientTokenQuery.setApiKey("YOUR API KEY");
//clientTokenQuery.setApiKeyPrefix("Token");
UserApi apiInstance = new UserApi();
Integer id = 56; // Integer | the user id
Long id = 789L; // Long | the user id
UserWithPass body = new UserWithPass(); // UserWithPass | the updated user
try {
User result = apiInstance.updateUser(id, body);
@@ -439,7 +439,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **Integer**| the user id |
**id** | **Long**| the user id |
**body** | [**UserWithPass**](UserWithPass.md)| the updated user |
### Return type

View File

@@ -5,7 +5,7 @@
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**admin** | **Boolean** | If the user is an administrator. | [optional]
**id** | **Integer** | The user id. |
**id** | **Long** | The user id. |
**name** | **String** | The user name. For login. |
**pass** | **String** | The user password. For login. |

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -13,7 +13,7 @@
package com.github.gotify.client;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class StringUtil {
/**
* Check if the given array contains the given value (with case-insensitive comparison).

View File

@@ -43,7 +43,7 @@ public interface ApplicationApi {
})
@DELETE("application/{id}")
Call<Void> deleteApp(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -70,7 +70,7 @@ public interface ApplicationApi {
})
@PUT("application/{id}")
Call<Application> updateApplication(
@retrofit2.http.Body Application body, @retrofit2.http.Path("id") Integer id
@retrofit2.http.Body Application body, @retrofit2.http.Path("id") Long id
);
/**
@@ -83,7 +83,7 @@ public interface ApplicationApi {
@retrofit2.http.Multipart
@POST("application/{id}/image")
Call<Application> uploadAppImage(
@retrofit2.http.Part("file\"; filename=\"file") RequestBody file, @retrofit2.http.Path("id") Integer id
@retrofit2.http.Part("file\"; filename=\"file") RequestBody file, @retrofit2.http.Path("id") Long id
);
}

View File

@@ -42,7 +42,7 @@ public interface ClientApi {
})
@DELETE("client/{id}")
Call<Void> deleteClient(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -57,4 +57,19 @@ public interface ClientApi {
Call<List<Client>> getClients();
/**
* Update a client.
*
* @param body the client to update (required)
* @param id the client id (required)
* @return Call&lt;Client&gt;
*/
@Headers({
"Content-Type:application/json"
})
@PUT("client/{id}")
Call<Client> updateClient(
@retrofit2.http.Body Client body, @retrofit2.http.Path("id") Long id
);
}

View File

@@ -0,0 +1,31 @@
package com.github.gotify.client.api;
import com.github.gotify.client.CollectionFormats.*;
import retrofit2.Call;
import retrofit2.http.*;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import com.github.gotify.client.model.Health;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public interface HealthApi {
/**
* Get health information.
*
* @return Call&lt;Health&gt;
*/
@Headers({
"Content-Type:application/json"
})
@GET("health")
Call<Health> getHealth();
}

View File

@@ -43,7 +43,7 @@ public interface MessageApi {
})
@DELETE("application/{id}/message")
Call<Void> deleteAppMessages(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -57,7 +57,7 @@ public interface MessageApi {
})
@DELETE("message/{id}")
Call<Void> deleteMessage(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -85,7 +85,7 @@ public interface MessageApi {
})
@GET("application/{id}/message")
Call<PagedMessages> getAppMessages(
@retrofit2.http.Path("id") Integer id, @retrofit2.http.Query("limit") Integer limit, @retrofit2.http.Query("since") Integer since
@retrofit2.http.Path("id") Long id, @retrofit2.http.Query("limit") Integer limit, @retrofit2.http.Query("since") Long since
);
/**
@@ -100,7 +100,7 @@ public interface MessageApi {
})
@GET("message")
Call<PagedMessages> getMessages(
@retrofit2.http.Query("limit") Integer limit, @retrofit2.http.Query("since") Integer since
@retrofit2.http.Query("limit") Integer limit, @retrofit2.http.Query("since") Long since
);
/**

View File

@@ -28,7 +28,7 @@ public interface PluginApi {
})
@POST("plugin/{id}/disable")
Call<Void> disablePlugin(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -42,7 +42,7 @@ public interface PluginApi {
})
@POST("plugin/{id}/enable")
Call<Void> enablePlugin(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -56,7 +56,7 @@ public interface PluginApi {
})
@GET("plugin/{id}/config")
Call<Object> getPluginConfig(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -70,7 +70,7 @@ public interface PluginApi {
})
@GET("plugin/{id}/display")
Call<String> getPluginDisplay(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -96,7 +96,7 @@ public interface PluginApi {
})
@POST("plugin/{id}/config")
Call<Void> updatePluginConfig(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
}

View File

@@ -56,7 +56,7 @@ public interface UserApi {
})
@DELETE("user/{id}")
Call<Void> deleteUser(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -70,7 +70,7 @@ public interface UserApi {
})
@GET("user/{id}")
Call<User> getUser(
@retrofit2.http.Path("id") Integer id
@retrofit2.http.Path("id") Long id
);
/**
@@ -111,7 +111,7 @@ public interface UserApi {
})
@POST("user/{id}")
Call<User> updateUser(
@retrofit2.http.Path("id") Integer id, @retrofit2.http.Body UserWithPass body
@retrofit2.http.Path("id") Long id, @retrofit2.http.Body UserWithPass body
);
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -27,13 +27,13 @@ import java.io.IOException;
* The Application holds information about an app which can send notifications.
*/
@ApiModel(description = "The Application holds information about an app which can send notifications.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class Application {
@SerializedName("description")
private String description = null;
@SerializedName("id")
private Integer id = null;
private Long id = null;
@SerializedName("image")
private String image = null;
@@ -70,7 +70,7 @@ public class Application {
* @return id
**/
@ApiModelProperty(example = "5", required = true, value = "The application id.")
public Integer getId() {
public Long getId() {
return id;
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -27,10 +27,10 @@ import java.io.IOException;
* The Client holds information about a device which can receive notifications (and other stuff).
*/
@ApiModel(description = "The Client holds information about a device which can receive notifications (and other stuff).")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class Client {
@SerializedName("id")
private Integer id = null;
private Long id = null;
@SerializedName("name")
private String name = null;
@@ -43,7 +43,7 @@ public class Client {
* @return id
**/
@ApiModelProperty(example = "5", required = true, value = "The client id.")
public Integer getId() {
public Long getId() {
return id;
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -27,7 +27,7 @@ import java.io.IOException;
* The Error contains error relevant information.
*/
@ApiModel(description = "The Error contains error relevant information.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class Error {
@SerializedName("error")
private String error = null;

View File

@@ -0,0 +1,117 @@
/*
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
package com.github.gotify.client.model;
import java.util.Objects;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.IOException;
/**
* Health represents how healthy the application is.
*/
@ApiModel(description = "Health represents how healthy the application is.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class Health {
@SerializedName("database")
private String database = null;
@SerializedName("health")
private String health = null;
public Health database(String database) {
this.database = database;
return this;
}
/**
* The health of the database connection.
* @return database
**/
@ApiModelProperty(example = "green", required = true, value = "The health of the database connection.")
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public Health health(String health) {
this.health = health;
return this;
}
/**
* The health of the overall application.
* @return health
**/
@ApiModelProperty(example = "green", required = true, value = "The health of the overall application.")
public String getHealth() {
return health;
}
public void setHealth(String health) {
this.health = health;
}
@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Health health = (Health) o;
return Objects.equals(this.database, health.database) &&
Objects.equals(this.health, health.health);
}
@Override
public int hashCode() {
return Objects.hash(database, health);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Health {\n");
sb.append(" database: ").append(toIndentedString(database)).append("\n");
sb.append(" health: ").append(toIndentedString(health)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -31,10 +31,10 @@ import org.threeten.bp.OffsetDateTime;
* The MessageExternal holds information about a message which was sent by an Application.
*/
@ApiModel(description = "The MessageExternal holds information about a message which was sent by an Application.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class Message {
@SerializedName("appid")
private Integer appid = null;
private Long appid = null;
@SerializedName("date")
private OffsetDateTime date = null;
@@ -43,7 +43,7 @@ public class Message {
private Map<String, Object> extras = null;
@SerializedName("id")
private Integer id = null;
private Long id = null;
@SerializedName("message")
private String message = null;
@@ -59,7 +59,7 @@ public class Message {
* @return appid
**/
@ApiModelProperty(example = "5", required = true, value = "The application id that send this message.")
public Integer getAppid() {
public Long getAppid() {
return appid;
}
@@ -103,7 +103,7 @@ public class Message {
* @return id
**/
@ApiModelProperty(example = "25", required = true, value = "The message id.")
public Integer getId() {
public Long getId() {
return id;
}
@@ -113,10 +113,10 @@ public class Message {
}
/**
* The actual message.
* The message. Markdown (excluding html) is allowed.
* @return message
**/
@ApiModelProperty(example = "Backup was successfully finished.", required = true, value = "The actual message.")
@ApiModelProperty(example = "**Backup** was successfully finished.", required = true, value = "The message. Markdown (excluding html) is allowed.")
public String getMessage() {
return message;
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -31,7 +31,7 @@ import java.util.List;
* Wrapper for the paging and the messages
*/
@ApiModel(description = "Wrapper for the paging and the messages")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class PagedMessages {
@SerializedName("messages")
private List<Message> messages = new ArrayList<Message>();

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -24,10 +24,10 @@ import io.swagger.annotations.ApiModelProperty;
import java.io.IOException;
/**
* The Paging holds holds information about the limit and making requests to the next page.
* The Paging holds information about the limit and making requests to the next page.
*/
@ApiModel(description = "The Paging holds holds information about the limit and making requests to the next page.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@ApiModel(description = "The Paging holds information about the limit and making requests to the next page.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class Paging {
@SerializedName("limit")
private Long limit = null;
@@ -36,7 +36,7 @@ public class Paging {
private String next = null;
@SerializedName("since")
private Integer since = null;
private Long since = null;
@SerializedName("size")
private Long size = null;
@@ -67,7 +67,7 @@ public class Paging {
* @return since
**/
@ApiModelProperty(example = "5", required = true, value = "The ID of the last message returned in the current request. Use this as alternative to the next link.")
public Integer getSince() {
public Long getSince() {
return since;
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -29,7 +29,7 @@ import java.util.List;
* Holds information about a plugin instance for one user.
*/
@ApiModel(description = "Holds information about a plugin instance for one user.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class PluginConf {
@SerializedName("author")
private String author = null;
@@ -41,7 +41,7 @@ public class PluginConf {
private Boolean enabled = null;
@SerializedName("id")
private Integer id = null;
private Long id = null;
@SerializedName("license")
private String license = null;
@@ -113,7 +113,7 @@ public class PluginConf {
* @return id
**/
@ApiModelProperty(example = "25", required = true, value = "The plugin id.")
public Integer getId() {
public Long getId() {
return id;
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -27,13 +27,13 @@ import java.io.IOException;
* The User holds information about permission and other stuff.
*/
@ApiModel(description = "The User holds information about permission and other stuff.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class User {
@SerializedName("admin")
private Boolean admin = null;
@SerializedName("id")
private Integer id = null;
private Long id = null;
@SerializedName("name")
private String name = null;
@@ -61,7 +61,7 @@ public class User {
* @return id
**/
@ApiModelProperty(example = "25", required = true, value = "The user id.")
public Integer getId() {
public Long getId() {
return id;
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -27,7 +27,7 @@ import java.io.IOException;
* The Password for updating the user.
*/
@ApiModel(description = "The Password for updating the user.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class UserPass {
@SerializedName("pass")
private String pass = null;

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -27,13 +27,13 @@ import java.io.IOException;
* The UserWithPass holds information about the credentials and other stuff.
*/
@ApiModel(description = "The UserWithPass holds information about the credentials and other stuff.")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class UserWithPass {
@SerializedName("admin")
private Boolean admin = null;
@SerializedName("id")
private Integer id = null;
private Long id = null;
@SerializedName("name")
private String name = null;
@@ -64,7 +64,7 @@ public class UserWithPass {
* @return id
**/
@ApiModelProperty(example = "25", required = true, value = "The user id.")
public Integer getId() {
public Long getId() {
return id;
}

View File

@@ -2,7 +2,7 @@
* Gotify REST-API.
* This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be either transmitted through a header named `X-Gotify-Key` or a query parameter named `token`. There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues)
*
* OpenAPI spec version: 1.0.6
* OpenAPI spec version: 2.0.1
*
*
* NOTE: This class is auto generated by the swagger code generator program.
@@ -27,7 +27,7 @@ import java.io.IOException;
* VersionInfo Model
*/
@ApiModel(description = "VersionInfo Model")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-02-17T19:42:51.206+01:00")
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-24T18:39:01.386+02:00")
public class VersionInfo {
@SerializedName("buildDate")
private String buildDate = null;

View File

@@ -43,7 +43,7 @@ public class ApplicationApiTest {
*/
@Test
public void deleteAppTest() {
Integer id = null;
Long id = null;
// Void response = api.deleteApp(id);
// TODO: test validations
@@ -67,7 +67,7 @@ public class ApplicationApiTest {
@Test
public void updateApplicationTest() {
Application body = null;
Integer id = null;
Long id = null;
// Application response = api.updateApplication(body, id);
// TODO: test validations
@@ -80,7 +80,7 @@ public class ApplicationApiTest {
@Test
public void uploadAppImageTest() {
File file = null;
Integer id = null;
Long id = null;
// Application response = api.uploadAppImage(file, id);
// TODO: test validations

View File

@@ -42,7 +42,7 @@ public class ClientApiTest {
*/
@Test
public void deleteClientTest() {
Integer id = null;
Long id = null;
// Void response = api.deleteClient(id);
// TODO: test validations
@@ -56,6 +56,19 @@ public class ClientApiTest {
public void getClientsTest() {
// List<Client> response = api.getClients();
// TODO: test validations
}
/**
* Update a client.
*
*
*/
@Test
public void updateClientTest() {
Client body = null;
Long id = null;
// Client response = api.updateClient(body, id);
// TODO: test validations
}
}

View File

@@ -0,0 +1,36 @@
package com.github.gotify.client.api;
import com.github.gotify.client.ApiClient;
import com.github.gotify.client.model.Health;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* API tests for HealthApi
*/
public class HealthApiTest {
private HealthApi api;
@Before
public void setup() {
api = new ApiClient().createService(HealthApi.class);
}
/**
* Get health information.
*
*
*/
@Test
public void getHealthTest() {
// Health response = api.getHealth();
// TODO: test validations
}
}

View File

@@ -43,7 +43,7 @@ public class MessageApiTest {
*/
@Test
public void deleteAppMessagesTest() {
Integer id = null;
Long id = null;
// Void response = api.deleteAppMessages(id);
// TODO: test validations
@@ -55,7 +55,7 @@ public class MessageApiTest {
*/
@Test
public void deleteMessageTest() {
Integer id = null;
Long id = null;
// Void response = api.deleteMessage(id);
// TODO: test validations
@@ -78,9 +78,9 @@ public class MessageApiTest {
*/
@Test
public void getAppMessagesTest() {
Integer id = null;
Long id = null;
Integer limit = null;
Integer since = null;
Long since = null;
// PagedMessages response = api.getAppMessages(id, limit, since);
// TODO: test validations
@@ -93,7 +93,7 @@ public class MessageApiTest {
@Test
public void getMessagesTest() {
Integer limit = null;
Integer since = null;
Long since = null;
// PagedMessages response = api.getMessages(limit, since);
// TODO: test validations

View File

@@ -30,7 +30,7 @@ public class PluginApiTest {
*/
@Test
public void disablePluginTest() {
Integer id = null;
Long id = null;
// Void response = api.disablePlugin(id);
// TODO: test validations
@@ -42,7 +42,7 @@ public class PluginApiTest {
*/
@Test
public void enablePluginTest() {
Integer id = null;
Long id = null;
// Void response = api.enablePlugin(id);
// TODO: test validations
@@ -54,7 +54,7 @@ public class PluginApiTest {
*/
@Test
public void getPluginConfigTest() {
Integer id = null;
Long id = null;
// Object response = api.getPluginConfig(id);
// TODO: test validations
@@ -66,7 +66,7 @@ public class PluginApiTest {
*/
@Test
public void getPluginDisplayTest() {
Integer id = null;
Long id = null;
// String response = api.getPluginDisplay(id);
// TODO: test validations
@@ -89,7 +89,7 @@ public class PluginApiTest {
*/
@Test
public void updatePluginConfigTest() {
Integer id = null;
Long id = null;
// Void response = api.updatePluginConfig(id);
// TODO: test validations

View File

@@ -55,7 +55,7 @@ public class UserApiTest {
*/
@Test
public void deleteUserTest() {
Integer id = null;
Long id = null;
// Void response = api.deleteUser(id);
// TODO: test validations
@@ -67,7 +67,7 @@ public class UserApiTest {
*/
@Test
public void getUserTest() {
Integer id = null;
Long id = null;
// User response = api.getUser(id);
// TODO: test validations
@@ -102,7 +102,7 @@ public class UserApiTest {
*/
@Test
public void updateUserTest() {
Integer id = null;
Long id = null;
UserWithPass body = null;
// User response = api.updateUser(id, body);

View File

@@ -1,6 +1,6 @@
#Fri May 08 13:09:14 CEST 2020
#Fri Jul 10 21:53:51 EEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-rc-4-all.zip