Because Jagex is going to release trading posts in the near future, I decided to dump the source code form my zybez mercher.
I used java because I wanted to implement it into a merching script.
//Main.java
package aiomercher.util.zybez;
import aiomercher.util.zybez.stages.Login;
import aiomercher.util.zybez.stages.Offer;
import aiomercher.util.zybez.utils.ZybezOffer;
/**
* Created by Xerion on 19-8-2014.
*/
public class Main {
static Login login;
public static void main(String args[]) throws Exception{
long time = System.currentTimeMillis();
login = new Login("***","****");
System.out.println("Logged-in in " + (System.currentTimeMillis() - time + 1) + " ms");
//You can add extra stuff here. For example adding an offer.
}
}
Stages//Login.java
package aiomercher.util.zybez.stages;
import aiomercher.util.zybez.utils.Requests;
import aiomercher.util.zybez.utils.Character;
import aiomercher.util.zybez.utils.ZybezOffer;
import aiomercher.util.zybez.utils.OfferType;
import java.net.*;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Xerion on 19-8-2014.
*/
public class Login {
public static boolean debug = false;
private String username,password;
/*Zybez Cookies*/
private String __cfduid,z_session_id,network_cookie,z_rteStatus,z_member_id,z_pass_hash;
public Login(String Username, String Password){
try {
/*Set Cookie manager*/
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
/*Login - Change this to post request for safety*/
Requests.sendGet("http://forums.zybez.net/index.php?app=curseauth&module=global§ion=login&do=process?auth_key=" + getAuth() + "&rememberMe=1&ips_username=" + URLEncoder.encode(Username, "UTF-8") + "&ips_password=" + URLEncoder.encode(Password, "UTF-8") + "&submit=Login");
//Requests.sendPost("http://forums.zybez.net/index.php?app=curseauth&module=global§ion=login&do=process","auth_key=" + getAuth() +"&rememberMe=1&ips_username=" + URLEncoder.encode(username, "UTF-8") + "&ips_password=" + URLEncoder.encode(password, "UTF-8") + "&submit=Login");
/*Fake this cookie*/
this.z_rteStatus = "rte";
/*Set all the variables*/
CookieStore cookieJar = manager.getCookieStore();
List<HttpCookie> cookies = cookieJar.getCookies();
for (HttpCookie cookie: cookies) {
if (cookie.getDomain().contains((".zybez.net"))) {
if(cookie.getName().equals("__cfduid")){
__cfduid = cookie.getValue();
}else if(cookie.getName().equals("z_session_id")){
z_session_id = cookie.getValue();
}else if(cookie.getName().equals("network_cookie")){
network_cookie = cookie.getValue();
}else if(cookie.getName().equals("z_member_id")) {
z_member_id = cookie.getValue();
}else if(cookie.getName().equals("z_pass_hash")){
z_pass_hash = cookie.getValue();
}else{
if(debug)
System.out.println("Unknown cookie : " + cookie.getName() + "\t" + cookie.getDomain());
}
}else{
if(debug)
System.out.println("Unknown website : " + cookie.getName() + "\t" + cookie.getDomain());
}
}
}catch (Exception ex){
ex.printStackTrace();
}
if(z_member_id == null || z_pass_hash == null){
throw new RuntimeException("Failed to login!");
}
}
private String getAuth() throws Exception{
String pattern = "<input type='hidden' name='auth_key' value='";
String response = Requests.sendGet("http://forums.zybez.net/index.php?app=curseauth&module=global§ion=login");
int beginIndex = response.indexOf(pattern) + pattern.length();
int endIndex = response.indexOf("' />", beginIndex);
return response.substring(beginIndex, endIndex);
}
public String getCookie(){
StringBuilder sb = new StringBuilder();
sb.append("__cfduid=" + __cfduid + "; ");
sb.append("network_cookie=" + network_cookie + "; ");
sb.append("z_rteStatus=" + z_rteStatus + "; ");
sb.append("z_member_id=" + z_member_id + "; ");
sb.append("z_pass_hash=" + z_pass_hash + "; ");
sb.append("z_session_id" + z_session_id + "; ");
return sb.toString();
}
public Character[] getCharacters(){
List<Character> character = new LinkedList<>();
try {
String response = Requests.sendGet("http://forums.zybez.net/runescape-2007-prices/274-water-rune", getCookie());
Matcher matcher = Pattern.compile("<option value=\"(.+?)\">(.+?)</option>$",Pattern.MULTILINE).matcher(response);
while (matcher.find()) {
if(debug)
System.out.println("Found character : " + matcher.group(1) + " " + matcher.group(2));
character.add(new Character(Integer.parseInt(matcher.group(1)),matcher.group(2)));
}
return character.toArray(new Character[character.size()]);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public ZybezOffer[] getCurrentOffers(){
List<ZybezOffer> zybezOffers = new LinkedList<>();
try {
String response = Requests.sendGet("http://forums.zybez.net/runescape-2007-prices", getCookie());
int beginIndex = response.indexOf("My Offers");
int endIndex = response.indexOf("</table>", beginIndex);
//System.out.println(response.substring(beginIndex,endIndex));
Matcher matcher = Pattern.compile("<tr>\\s*<td class=\"nowrap\"><h3><a href=\"(.*?)\">(.*?)<.*?$\\s*.*\\s*.*title=\"(.*?)\" class.*?\\s*.*?>(.*?)<\\/.*$\\s*(.*?) for (.*?) GP\\s*.*\\s*.*\\s*.*?title=\"(.*?)\">(.*?)<\\/span><\\/td>\\s*.*?\">(.*?) GP<\\/td>\\s*<td>\\s*<a href=\"(.*?)\"><img src=\"(.*?)\" title=\"Delete\" \\/><\\/a>\\s*<a href=\"(.*?)\"><img src=\"(.*?)\" title=\"Mark this offer complete\" \\/><\\/a>\\s*<\\/td>\\s*<\\/tr>",Pattern.MULTILINE).matcher(response.substring(beginIndex,endIndex));
while (matcher.find()) {
if(debug)
System.out.println("Found offer : " + matcher.group(1) + " " + matcher.group(2) + " " + matcher.group(3) + " for " + matcher.group(4) + "GP\t" + matcher.group(5) + "\t" + matcher.group(6));
zybezOffers.add(new ZybezOffer(matcher.group(2),matcher.group(3),matcher.group(1),matcher.group(3).equals("Selling") ? OfferType.SELL : OfferType.BUY,Integer.parseInt(matcher.group(5).replaceAll(",", "")),Integer.parseInt(matcher.group(6).replaceAll(",", "")),matcher.group(7),1,matcher.group(8),matcher.group(12)));
}
return zybezOffers.toArray(new ZybezOffer[zybezOffers.size()]);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public ZybezOffer[] getCompleteOffers(){
List<ZybezOffer> zybezOffers = new LinkedList<>();
try {
String response = Requests.sendGet("http://forums.zybez.net/runescape-2007-prices", getCookie());
int beginIndex = response.indexOf("My Offers");
int endIndex = response.indexOf("</table>", beginIndex);
Matcher matcher = Pattern.compile("<tr class=\"done\">\\s*<td class=\\\"nowrap\\\"><h3><a href=\"(.*?)\">(.*?)<.*?$\\s*.*\\s*.*title=\"(.*?)\" class.*?\\s*.*?>(.*?)<\\/.*$\\s*(.*?) for (.*?) GP\\s*.*\\s*.*\\s*.*?title=\\\"(.*?)\\\">(.*?)<\\/span><\\/td>\\s*.*?\\\">(.*?) GP<\\/td>\\s*<td>\\s*<a href=\\\"(.*?)\\\"><img src=\\\"(.*?)\\\" title=\\\"Delete\\\" \\/><\\/a>\\s*<a href=\\\"(.*?)\\\"><img src=\\\"(.*?)\\\" title=\\\"Mark this offer complete\\\" \\/><\\/a>\\s*<\\/td>\\s*<\\/tr>",Pattern.MULTILINE).matcher(response.substring(beginIndex,endIndex));
while (matcher.find()) {
if(debug)
System.out.println("Found offer : " + matcher.group(1) + " " + matcher.group(2) + " " + matcher.group(3) + " for " + matcher.group(4) + "GP\t" + matcher.group(5) + "\t" + matcher.group(6));
zybezOffers.add(new ZybezOffer(matcher.group(2),matcher.group(3),matcher.group(1),matcher.group(3).equals("Selling") ? OfferType.SELL : OfferType.BUY,Integer.parseInt(matcher.group(5).replaceAll(",", "")),Integer.parseInt(matcher.group(6).replaceAll(",", "")),matcher.group(7),1,matcher.group(10),matcher.group(12)));
}
return zybezOffers.toArray(new ZybezOffer[zybezOffers.size()]);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
//Stages//Offer.java
package aiomercher.util.zybez.stages;
import aiomercher.util.zybez.utils.*;
import aiomercher.util.zybez.utils.Character;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Xerion on 19-8-2014.
*/
public class Offer {
Login login;
public Offer(Login login){
this.login = login;
}
/**
* Add an offer to Zybez
*
* @param id Item ID
* @param offerType The Offer type (buy or sell)
* @param quantity The amount you want to buy/sell
* @param price The price you want to buy/sell the item for
* @param character The character you want to appear in the offer
* @param contactMode The contact mode you want to specify (PM or CC)
* @return True if the offer is placed on Zybez
*/
public boolean createOffer(int id,OfferType offerType,int quantity, int price, Character character, ContactMode contactMode){
return createOffer(getAuth(id),id,offerType.getValue(),quantity,price,character.getId(),contactMode.getValue(),"",login.getCookie());
}
/**
* Add an offer to Zybez
*
* @param id Item ID
* @param offerType The Offer type (buy or sell)
* @param quantity The amount you want to buy/sell
* @param price The price you want to buy/sell the item for
* @param character The character you want to appear in the offer
* @param contactMode The contact mode you want to specify (PM or CC)
* @param notes The Notes you want to add in the offer
* @return True if the offer is placed on Zybez
*/
public boolean createOffer(int id,OfferType offerType,int quantity, int price, Character character, ContactMode contactMode, String notes){
return createOffer(getAuth(id),id,offerType.getValue(),quantity,price,character.getId(),contactMode.getValue(),notes,login.getCookie());
}
private boolean createOffer(String auth, int id, int type, int quantity, int price, int characterId, int contact, String notes, String Cookie){
String url = "http://forums.zybez.net/index.php?app=priceguide&module=public§ion=action&do=trade-add";
System.out.println("auth: "+(auth!=null?auth:"null")+", id: "+id+", type: "+type+", price: "+price+", charId: "+characterId+", contact: "+contact+", note: "+notes+", cookie: "+(Cookie!=null?Cookie.toString():"null"));
try{
String urlParameters = "auth=" + URLEncoder.encode(auth, "UTF-8") + "&id=" + URLEncoder.encode(Integer.toString(id), "UTF-8")
+"&type=" + URLEncoder.encode(Integer.toString(type), "UTF-8") + "&qty=" + URLEncoder.encode(Integer.toString(quantity), "UTF-8")
+"&price=" + URLEncoder.encode(Integer.toString(price), "UTF-8") + "&character_id=" + URLEncoder.encode(Integer.toString(characterId), "UTF-8")
+"&contact=" + URLEncoder.encode(Integer.toString(contact), "UTF-8")+ "¬es=" + URLEncoder.encode(notes, "UTF-8");
if(Requests.sendGet(url + "?" + urlParameters,Cookie).contains("Your trade has been added to the system.")){
return true;
}
return false;
}catch (Exception ex){
ex.printStackTrace();
return false;
}
}
public String getAuth(int id){
try{
String response = Requests.sendGet(getSite(id),login.getCookie());
Matcher matcher = Pattern.compile("<input type=\"hidden\" name=\"auth\" value=\"(.+?)\" />").matcher(response);
if (matcher.find()){
return (matcher.group(1));
}else{
throw new RuntimeException("Failed to find the auth");
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private String getSite(int id){
try{
String response = Requests.sendGet("http://forums.zybez.net/index.php?app=priceguide&module=public§ion=list");
Matcher matcher = Pattern.compile("<a href=\"(http://forums.zybez.net/runescape-2007-prices/" + id + "-.*?)\">").matcher(response);
if (matcher.find()){
return matcher.group(1);
}else{
throw new RuntimeException("ID is invalid!");
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/*
public static String getItemName(int id){
try{
String response = Requests.sendGet("http://forums.zybez.net/runescape-2007-prices/api/item/" + id);
Matcher matcher = Pattern.compile("name\":\"(.+?)\",\"type").matcher(response);
if (matcher.find()){
String result = matcher.group(1);
//System.out.println(result);
//result = result.replace(' ', '-');
//result = result.replace("(", "").replace(")", "");
//System.out.println(result);
return result;
}else{
throw new RuntimeException("Cannot find item name!");
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
*/
public static enum OfferType {
BUY(0), SELL(1);
private final int value;
private OfferType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public static enum ContactMode {
PM(1), CC(3);
private final int value;
private ContactMode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}
//utils/Character.java
package aiomercher.util.zybez.utils;
/**
* Created by Xerion on 19-8-2014.
*/
public class Character {
private int id;
private String accountName;
/**
*
* @param id ZYbez account id
* @param accountName Runescape account name
*/
public Character(int id, String accountName){
this.id = id;
this.accountName = accountName;
}
public int getId() {
return id;
}
public String getAccountName() {
return accountName;
}
@Override
public String toString(){
return this.accountName;
}
}
//utils//OfferType.java
package aiomercher.util.zybez.utils;
/**
* Created by Xerion on 25-8-2014.
*/
public enum OfferType {
BUY(0), SELL(1);
private final int value;
private OfferType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return this.name().substring(0, 1).toUpperCase() + this.name().substring(1).toLowerCase();
}
}
//utils//Requests.java
package aiomercher.util.zybez.utils;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Created by Xerion on 19-8-2014.
*/
public class Requests {
public static boolean debug = false;
public static String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36";
public static String sendGet(String targetURL) throws Exception {
return sendGet(targetURL,null);
}
public static String sendGet(String targetURL, String cookie) throws Exception {
String url = targetURL;
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
//add cookie
if(cookie != null)
con.setRequestProperty("Cookie" , cookie);
int responseCode = con.getResponseCode();
if(debug) {
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Follow redirects: " + con.getInstanceFollowRedirects());
System.out.println("Response Code : " + responseCode);
}
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
response.append("\n");
}
in.close();
if(debug) {
for (String s : con.getHeaderFields().get("Set-Cookie")) {
System.out.println(s);
}
}
//return result
return response.toString();
}
}
//utils//ZybezOffer.java
package aiomercher.util.zybez.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Xerion on 25-8-2014.
*/
public class ZybezOffer {
private int amount, price;
private String itemName, itemLink, itemOwner;
private long epoch;
private OfferType offerType;
private String completeUrl, deleteUrl;
private int place;
public ZybezOffer(String ItemName,String owner, String Link , OfferType OfferType, int Amount, int Price, String Time, int place) throws ParseException {
this.itemName = ItemName;
this.itemLink = Link;
this.itemOwner = owner.replace("Verified owner of ", "");
this.offerType = OfferType;
this.amount = Amount;
this.price = Price;
this.place = place;
this.epoch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz").parse(Time).getTime();
}
public ZybezOffer(String ItemName,String owner, String Link , OfferType OfferType, int Amount, int Price, String Time, int place, String CompleteUrl, String DeleteUrl) throws ParseException {
this.itemName = ItemName;
this.offerType = OfferType;
this.itemLink = Link;
this.itemOwner = owner.replace("Verified owner of ", "");;
this.amount = Amount;
this.price = Price;
this.place = place;
this.epoch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz").parse(Time).getTime();
this.completeUrl = CompleteUrl;
this.deleteUrl = DeleteUrl;
}
public int getPrice() {
return price;
}
//public int getPlace(){ return place; }
public int getAmount() {
return amount;
}
public String getItemName() {
return itemName;
}
public long getEpoch() {
return epoch;
}
public OfferType getOfferType() {
return offerType;
}
public Date getDate(){
return new Date(epoch);
}
public void completeOffer(String Cookie){
try {
System.out.println(completeUrl);
System.out.println(Cookie);
Requests.sendGet(completeUrl, Cookie);
}catch (Exception e){
e.printStackTrace();
}
}
public void deleteOffer(String Cookie){
try {
System.out.println(deleteUrl);
System.out.println(Cookie);
Requests.sendGet(deleteUrl, Cookie);
}catch (Exception e){
e.printStackTrace();
}
}
public int getPlace(){
try {
String response = Requests.sendGet(this.itemLink);
int beginIndex = response.indexOf("<table class=\"ipb_table topic_list\">");
int endIndex = response.indexOf("</table>", beginIndex);
//System.out.println(response.substring(beginIndex,endIndex));
Matcher matcher = Pattern.compile("<tr>\\s*<td class=\"nowrap\">\\s*.*?title=\"(.*?)\" class.*\\s*.*\\s*.*\\s*.*\\s*.*\\s*.*\\s*.*?<span title=\"(.*?)\">", Pattern.MULTILINE).matcher(response.substring(beginIndex,endIndex));
int place = 1;
while (matcher.find()) {
if(this.itemOwner.equals(matcher.group(1).replace("Verified owner of ", "")) && new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz").parse(matcher.group(2)).getTime() == this.epoch){
return place;
}else{
place++;
}
//System.out.println(matcher.group(1) + "\t" + matcher.group(2));
}
}catch (Exception e){
e.printStackTrace();
}
return -1;
}
@Override
public String toString() {
return offerType + "ing " + getAmount() + " × "+ itemName + " for " + getPrice() + "ea";
}
}
You are free to use the source code in anyway you like if you give credits to me.
Constructive feedback is welcome. However I'm probably not going to change it.