/* * part of bidwatcher * Author: Jan Starzynski * use of this code is restricted to the terms * of the GNU GPL, which should have been included in this * distribution. If not, see www.gnu.org/copyleft/gpl.html. * Here is the short version: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * $Id: bidgui.cpp,v 1.1.2.12 2004/09/25 22:34:37 kevindication Exp $ * * View and Control for Bidgroups */ #include "config.h" #include #include #include #include #include #ifdef HAVE_STL # include # include # include # include #else # include # include # include #endif #include "bidgui.h" #include "portability.h" using namespace std; // Replaces or removes ascii characters > 127. On some system they are not properly shown. void removeAscii127(char *info) { unsigned char *p = (unsigned char*)info; while(*p) { switch(*p) { case (unsigned char)'ä': *p = 'a'; break; case (unsigned char)'ö': *p = 'o'; break; case (unsigned char)'ü': *p = 'u'; break; case (unsigned char)'Ä': *p = 'A'; break; case (unsigned char)'Ö': *p = 'O'; break; case (unsigned char)'Ü': *p = 'u'; break; case (unsigned char)'ß': *p = 's'; break; } if(*p > 127) *p = ' '; p++; } } BidGroup *getBidGroup() { static BidGroup bid_group; return &bid_group; } static bool hasBid(struct auctioninfo *auc) { if(auc->isSnipe) return true; if(auc->snipeAmount > 0) return true; if(auc->myBidAmount > 0) return true; return false; } static void copySnipe(struct auctioninfo *dst, const struct auctioninfo *src) { float new_price = 0; if(strcmp(src->currency, dst->currency) == 0) { new_price = src->myBidAmount; if(strcmp(src->currency, src->ShippingCur[0]) == 0 && strcmp(src->currency, dst->ShippingCur[0]) == 0) { new_price += src->Shipping[0] - dst->Shipping[0]; } } if(new_price < 0) new_price = 0; setBid(dst, new_price, src->myBidQuantity, true, false); } // set/change bidgroup for an item void switchBidGroup(struct auctioninfo *auction[], int auc_num, int current_auc, int new_auc, const char *subdir, int time_diff, const char *auth_id) { if(current_auc < 0 || current_auc >= auc_num) return; if(new_auc < 0 || new_auc >= auc_num) return; BidGroup *group = getBidGroup(); struct auctioninfo *cauc = auction[current_auc]; struct auctioninfo *auc = auction[new_auc]; BidGroup::IdType cid = cauc->ItemNumber; BidGroup::IdType id = auc->ItemNumber; int cgid = group->groupId(cid); // int gid = group->groupId(id); if(cgid >= 0) group->delItem(id); group->addItem(cid, id); group->sweepList(); if(hasBid(cauc) && !hasBid(auc)) copySnipe(auc, cauc); if(!hasBid(cauc) && hasBid(auc)) copySnipe(cauc, auc); setBidGroupAuction(auction, auc_num, auth_id); UpdateList(); WriteAucFile(); } char *configFileName(char *file, const char *subdir, const char *fname) { sprintf(file, "%s/%s/%s", getenv("HOME"), subdir, fname); return file; } char *bidGroupFile(char *file, const char *subdir) { return configFileName(file, subdir, "bidgroup.cfg"); } void writeBidGroup(const char *subdir) { char file[200]; BidGroup *group = getBidGroup(); group->write(bidGroupFile(file, subdir)); } void readBidGroup(const char *subdir) { char file[200]; BidGroup *group = getBidGroup(); group->clear(); group->read(bidGroupFile(file, subdir)); } void bidGroupComment(char **str, struct auctioninfo *auction[], int auc) { BidGroup *group = getBidGroup(); const int gid = group->groupId(auction[auc]->ItemNumber); if(group->numGroup() > 0) { if(gid >= 0) *str = g_strdup_printf(" %*s%d%*s: %s", gid, "", gid + 1, group->numGroup() - gid - 1, "", *str); else *str = g_strdup_printf(" %*s : %s", group->numGroup() - 1, "", *str); } } SetBidGroupAuction::~SetBidGroupAuction() { setBidGroupAuction(auction, auc_num, auth_id); } // mark all items in a successful bidgroup #if HAVE_BIDGROUP static void findSucceededAuc(map &succeeded, const BidGroup::ItemList *list) { if(!list) return; bool any_succeeded = false; for(BidGroup::ItemList::const_iterator it = list->begin(); it != list->end(); ++it) { if(succeeded[*it]) { any_succeeded = true; break; } } if(any_succeeded) { for(BidGroup::ItemList::const_iterator it = list->begin(); it != list->end(); ++it) { succeeded[*it] = any_succeeded; } } } // I won this auction. static bool isMine(struct auctioninfo *auction, const char *auth_id) { return strcmp(auction->HighBidder, auth_id) == 0 && auction->UpdTime >= auction->EndsValue; } #endif void setBidGroupAuction(struct auctioninfo *auction[], int auc_num, const char *auth_id) { #if HAVE_BIDGROUP BidGroup *group = getBidGroup(); map succeeded; for(int i = 0; i < auc_num; i++) { struct auctioninfo *a = auction[i]; succeeded[a->ItemNumber] = isMine(a, auth_id); } for(int i = 0; i < group->numGroup(); i++) { findSucceededAuc(succeeded, group->getGroup(i)); } for(int i = 0; i < auc_num; i++) { struct auctioninfo *a = auction[i]; if(a->isSnipe && !isMine(a, auth_id) && succeeded[a->ItemNumber]) { printf("clear snipe "LLU_FMT"\n", a->ItemNumber); ClearSnipe(i); } } #endif } void delBidGroupItem(struct auctioninfo *auction[], int auc) { BidGroup *group = getBidGroup(); group->delItem(auction[auc]->ItemNumber); group->sweepList(); } // save something in a file defined by format void savePage(const char *page, const char *format, ...) { va_list va; va_start(va, format); char fname[4096]; vsprintf(fname, format, va); va_end(va); FILE *fp = fopen(fname, "w"); if(fp) { fprintf(fp, "%s", page); fclose(fp); } } // set up a bid or snipe void setBid(struct auctioninfo *auction, float bid, int quantity, bool snipe, bool fire_bid) { if(!auction) return; auction->isSnipe = snipe; auction->isPreBid = snipe; auction->myBidAmount = bid; auction->myBidQuantity = quantity; memset(auction->snipeKey, 0, sizeof(auction->snipeKey)); if(snipe) { auction->snipeAmount = bid; auction->snipeQty = quantity; } else { auction->snipeAmount = 0; auction->snipeQty = 0; auction->getkey(bid, quantity); if(fire_bid && auction->snipeKey[0]) auction->bid(FALSE); } UpdateList(); } // set up a bid or snipe reading amount + quantity from a file static struct auctioninfo *setBid(struct auctioninfo *auction, FILE *fp, bool snipe, bool fire_bid) { if(!auction) return auction; float bid; int qty; if(fscanf(fp, "%f%d", &bid, &qty) != 2) return auction; setBid(auction, bid, qty, snipe, fire_bid); fprintf(stderr, "%s "LLU_FMT" bid: %f qty: %d\n", snipe ? "snipeing" : "bidding ", auction->ItemNumber, bid, qty); return auction; } static void lockFile(FILE *fp, bool rw, bool lock) { struct flock tmp; tmp.l_type = lock ? rw ? F_WRLCK : F_RDLCK : F_UNLCK; tmp.l_whence = SEEK_SET; tmp.l_start = 0; tmp.l_len = 0; fcntl(fileno(fp), F_SETLKW, &tmp); } /* * Adds items from the file "~/.bidwatcher/item.add" to bidwatcher. * Places bids/snipes if required. * * Syntax: a continuous stream of the following command * "ebay-id" adds an item * "add ebay-id" adds an item * "bid ebay-id amount quantity" bids for an item * "snipe ebay-id amount quantity" snipes for an item * * Example: * 568880089 * add 568880010 * bid 568888888 10.51 1 * snipe 568888777 12.11 1 * * I use this to remotely control my bidwatcher via email-filters. */ void addItemsFromFile(const char *subdir, volatile bool &up_in_prog) { class AutoFp { FILE *fp; public: AutoFp(FILE *fp, bool rw): fp(fp) { if(!fp) return; lockFile(fp, rw, true); } ~AutoFp() { if(!fp) return; fflush(fp); lockFile(fp, false, false); fclose(fp); } operator FILE*() const { return fp; } FILE* operator->() const { return fp; } }; class AutoFlag { volatile bool &up_in_prog; public: AutoFlag(volatile bool &up_in_prog): up_in_prog(up_in_prog) { up_in_prog = true; } ~AutoFlag() { up_in_prog = false;} }; if(up_in_prog) return; AutoFlag a_flag(up_in_prog); if(interfereWithSnipe()) return; char file[256]; configFileName(file, subdir, "item.add"); AutoFp fp(fopen(file, "r+"), true); if(!fp) return; char buffer1[20]; char buffer2[20]; char *rd = buffer1; char *act = buffer2; const char *def_action = "add"; strcpy(act, def_action); while(fscanf(fp, "%19s", rd) == 1) { if(interfereWithSnipe()) return; unsigned long long id; if(sscanf(rd, LLU_FMT, &id) != 1) { char *tmp = rd; rd = act; act = tmp; continue; } up_in_prog = false; if(strcmp(act, "add") == 0) { fprintf(stderr, "adding "LLU_FMT"\n", id); addNewItem(id); } else if(strcmp(act, "bid") == 0) { setBid(addNewItem(id), fp, false, true); } else if(strcmp(act, "snipe") == 0) { setBid(addNewItem(id), fp, true, false); } else { fprintf(stderr, "ignoring %s "LLU_FMT"\n", act, id); } up_in_prog = true; strcpy(act, def_action); } ftruncate(fileno(fp), 0); }