Remove examine api

The non-items examine info has been broken for years, and the wiki already has item examines anyway, so we can use those in the future if we need them.
This commit is contained in:
Adam
2021-06-13 13:43:53 -04:00
parent 141d4eac0d
commit 86a79a1509
7 changed files with 1 additions and 524 deletions

View File

@@ -1,94 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.api.examine;
import java.io.IOException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
@Slf4j
@RequiredArgsConstructor
public class ExamineClient
{
private static final MediaType TEXT = MediaType.parse("text");
private final OkHttpClient client;
public void submitObject(int id, String text)
{
submit("object", id, text);
}
public void submitNpc(int id, String text)
{
submit("npc", id, text);
}
public void submitItem(int id, String text)
{
submit("item", id, text);
}
private void submit(String type, int id, String text)
{
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("examine")
.addPathSegment(type)
.addPathSegment(Integer.toString(id))
.build();
log.debug("Built URI: {}", url);
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(TEXT, text))
.build();
client.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
log.warn("Error submitting examine", e);
}
@Override
public void onResponse(Call call, Response response)
{
response.close();
log.debug("Submitted examine info for {} {}: {}", type, id, text);
}
});
}
}

View File

@@ -1,96 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service.examine;
import static net.runelite.http.service.examine.ExamineType.ITEM;
import static net.runelite.http.service.examine.ExamineType.NPC;
import static net.runelite.http.service.examine.ExamineType.OBJECT;
import net.runelite.http.service.item.ItemEntry;
import net.runelite.http.service.item.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/examine")
public class ExamineController
{
private final ExamineService examineService;
private final ItemService itemService;
@Autowired
public ExamineController(ExamineService examineService, ItemService itemService)
{
this.examineService = examineService;
this.itemService = itemService;
}
@GetMapping("/npc/{id}")
public String getNpc(@PathVariable int id)
{
return examineService.get(NPC, id);
}
@GetMapping("/object/{id}")
public String getObject(@PathVariable int id)
{
return examineService.get(OBJECT, id);
}
@GetMapping("/item/{id}")
public String getItem(@PathVariable int id)
{
// Tradeable item examine info is available from the Jagex item API
ItemEntry item = itemService.getItem(id);
if (item != null)
{
return item.getDescription();
}
return examineService.get(ITEM, id);
}
@RequestMapping(path = "/npc/{id}", method = POST)
public void submitNpc(@PathVariable int id, @RequestBody String examine)
{
examineService.insert(NPC, id, examine);
}
@RequestMapping(path = "/object/{id}", method = POST)
public void submitObject(@PathVariable int id, @RequestBody String examine)
{
examineService.insert(OBJECT, id, examine);
}
@RequestMapping(path = "/item/{id}", method = POST)
public void submitItem(@PathVariable int id, @RequestBody String examine)
{
examineService.insert(ITEM, id, examine);
}
}

View File

@@ -1,86 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service.examine;
import java.time.Instant;
public class ExamineEntry
{
private ExamineType type;
private int id;
private Instant time;
private int count;
private String text;
public ExamineType getType()
{
return type;
}
public void setType(ExamineType type)
{
this.type = type;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public Instant getTime()
{
return time;
}
public void setTime(Instant time)
{
this.time = time;
}
public int getCount()
{
return count;
}
public void setCount(int count)
{
this.count = count;
}
public String getText()
{
return text;
}
public void setText(String text)
{
this.text = text;
}
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service.examine;
import java.sql.Timestamp;
import java.time.Instant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.sql2o.Connection;
import org.sql2o.Sql2o;
@Service
public class ExamineService
{
private static final String CREATE_EXAMINE = "CREATE TABLE IF NOT EXISTS `examine` (\n"
+ " `type` enum('OBJECT','NPC','ITEM') NOT NULL,\n"
+ " `id` int(11) NOT NULL,\n"
+ " `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n"
+ " `count` int(11) NOT NULL,\n"
+ " `text` tinytext NOT NULL,\n"
+ " UNIQUE KEY `type` (`type`,`id`,`text`(64))\n"
+ ") ENGINE=InnoDB";
private final Sql2o sql2o;
@Autowired
public ExamineService(@Qualifier("Runelite SQL2O") Sql2o sql2o)
{
this.sql2o = sql2o;
try (Connection con = sql2o.open())
{
con.createQuery(CREATE_EXAMINE)
.executeUpdate();
}
}
public String get(ExamineType type, int id)
{
try (Connection con = sql2o.open())
{
ExamineEntry entry = con.createQuery("select text from examine where type = :type and id = :id "
+ "order by count desc limit 1")
.addParameter("type", type.toString())
.addParameter("id", id)
.executeAndFetchFirst(ExamineEntry.class);
if (entry != null)
{
return entry.getText();
}
}
return null;
}
public void insert(ExamineType type, int id, String examine)
{
try (Connection con = sql2o.open())
{
con.createQuery("insert into examine (type, id, time, count, text) values "
+ "(:type, :id, :time, :count, :text) on duplicate key update count = count + 1")
.addParameter("type", type.toString())
.addParameter("id", id)
.addParameter("time", Timestamp.from(Instant.now()))
.addParameter("count", 1)
.addParameter("text", examine)
.executeUpdate();
}
}
}

View File

@@ -1,32 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service.examine;
public enum ExamineType
{
OBJECT,
NPC,
ITEM;
}

View File

@@ -25,13 +25,9 @@
package net.runelite.client.plugins.examine;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.inject.Provides;
import java.time.Instant;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.regex.Pattern;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType;
@@ -58,14 +54,7 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.QuantityFormatter;
import net.runelite.client.util.Text;
import net.runelite.http.api.examine.ExamineClient;
import okhttp3.OkHttpClient;
/**
* Submits examine info to the api
*
* @author Adam
*/
@PluginDescriptor(
name = "Examine",
description = "Shows additional examine information (eg. GE Average, HA Value)",
@@ -74,15 +63,7 @@ import okhttp3.OkHttpClient;
@Slf4j
public class ExaminePlugin extends Plugin
{
private static final Pattern X_PATTERN = Pattern.compile("^\\d+ x ");
private final Deque<PendingExamine> pending = new ArrayDeque<>();
private final Cache<CacheKey, Boolean> cache = CacheBuilder.newBuilder()
.maximumSize(128L)
.build();
@Inject
private ExamineClient examineClient;
@Inject
private Client client;
@@ -93,12 +74,6 @@ public class ExaminePlugin extends Plugin
@Inject
private ChatMessageManager chatMessageManager;
@Provides
ExamineClient provideExamineClient(OkHttpClient okHttpClient)
{
return new ExamineClient(okHttpClient);
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
@@ -222,7 +197,6 @@ public class ExaminePlugin extends Plugin
log.debug("Got examine for {} {}: {}", pendingExamine.getType(), pendingExamine.getId(), event.getMessage());
// If it is an item, show the price of it
final ItemComposition itemComposition;
if (pendingExamine.getType() == ExamineType.ITEM || pendingExamine.getType() == ExamineType.ITEM_BANK_EQ)
{
final int itemId = pendingExamine.getId();
@@ -233,35 +207,9 @@ public class ExaminePlugin extends Plugin
return;
}
itemComposition = itemManager.getItemComposition(itemId);
final ItemComposition itemComposition = itemManager.getItemComposition(itemId);
getItemPrice(itemComposition.getId(), itemComposition, itemQuantity);
}
else
{
itemComposition = null;
}
// Don't submit examine info for tradeable items, which we already have from the RS item api
if (itemComposition != null && itemComposition.isTradeable())
{
return;
}
// Large quantities of items show eg. 100000 x Coins
if (type == ExamineType.ITEM && X_PATTERN.matcher(event.getMessage()).lookingAt())
{
return;
}
CacheKey key = new CacheKey(type, pendingExamine.getId());
Boolean cached = cache.getIfPresent(key);
if (cached != null)
{
return;
}
cache.put(key, Boolean.TRUE);
submitExamine(pendingExamine, event.getMessage());
}
private int[] findItemFromWidget(int widgetId, int actionParam)
@@ -407,23 +355,4 @@ public class ExaminePlugin extends Plugin
.build());
}
}
private void submitExamine(PendingExamine examine, String text)
{
int id = examine.getId();
switch (examine.getType())
{
case ITEM:
examineClient.submitItem(id, text);
break;
case OBJECT:
examineClient.submitObject(id, text);
break;
case NPC:
examineClient.submitNpc(id, text);
break;
}
}
}

View File

@@ -28,28 +28,19 @@ import com.google.inject.Guice;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.ItemComposition;
import net.runelite.api.ItemID;
import net.runelite.api.MenuAction;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.widgets.Widget;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.game.ItemManager;
import net.runelite.http.api.examine.ExamineClient;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import org.mockito.Mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@@ -60,10 +51,6 @@ public class ExaminePluginTest
@Inject
ExaminePlugin examinePlugin;
@Mock
@Bind
ExamineClient examineClient;
@Mock
@Bind
Client client;
@@ -82,43 +69,6 @@ public class ExaminePluginTest
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
@Test
public void testItem()
{
when(client.getWidget(anyInt(), anyInt())).thenReturn(mock(Widget.class));
when(itemManager.getItemComposition(anyInt())).thenReturn(mock(ItemComposition.class));
MenuOptionClicked menuOptionClicked = new MenuOptionClicked();
menuOptionClicked.setMenuOption("Examine");
menuOptionClicked.setMenuAction(MenuAction.EXAMINE_ITEM);
menuOptionClicked.setId(ItemID.ABYSSAL_WHIP);
examinePlugin.onMenuOptionClicked(menuOptionClicked);
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.ITEM_EXAMINE, "", "A weapon from the abyss.", "", 0);
examinePlugin.onChatMessage(chatMessage);
// This passes due to not mocking the ItemComposition for the whip
verify(examineClient).submitItem(anyInt(), anyString());
}
@Test
public void testLargeStacks()
{
when(client.getWidget(anyInt(), anyInt())).thenReturn(mock(Widget.class));
when(itemManager.getItemComposition(anyInt())).thenReturn(mock(ItemComposition.class));
MenuOptionClicked menuOptionClicked = new MenuOptionClicked();
menuOptionClicked.setMenuOption("Examine");
menuOptionClicked.setMenuAction(MenuAction.EXAMINE_ITEM);
menuOptionClicked.setId(ItemID.ABYSSAL_WHIP);
examinePlugin.onMenuOptionClicked(menuOptionClicked);
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.ITEM_EXAMINE, "", "100000 x Abyssal whip", "", 0);
examinePlugin.onChatMessage(chatMessage);
verify(examineClient, never()).submitItem(anyInt(), anyString());
}
@Test
public void testGetItemPrice()
{