Skip to content

Commit a019729

Browse files
author
Freddie
committed
Oops, templates went missing.
Add initial SQL to import 2 corporations. Add API updater to do various things, including retrieving character IDs and corporation wallet/transactions.
1 parent e44c08c commit a019729

7 files changed

Lines changed: 316 additions & 0 deletions

File tree

api_updater.py

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
#!/usr/bin/env python
2+
3+
import cPickle
4+
import datetime
5+
import os
6+
import urllib2
7+
import xml.etree.ElementTree as ET
8+
from decimal import *
9+
from urllib import urlencode
10+
11+
# Aurgh
12+
from django.core.management import setup_environ
13+
import settings
14+
setup_environ(settings)
15+
16+
from rdi.models import *
17+
18+
19+
BASE_URL = 'http://api.eve-online.com'
20+
CHARACTERS_URL = '%s/account/Characters.xml.aspx' % (BASE_URL)
21+
TRANSACTIONS_URL = '%s/corp/WalletTransactions.xml.aspx' % (BASE_URL)
22+
WALLET_URL = '%s/corp/AccountBalance.xml.aspx' % (BASE_URL)
23+
24+
25+
def main():
26+
_now = datetime.datetime.now
27+
28+
# Load cache
29+
cache_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cache/cache.pickle')
30+
if os.path.exists(cache_filepath):
31+
cache = cPickle.load(open(cache_filepath, 'rb'))
32+
else:
33+
cache = {
34+
'char': {},
35+
'corp': {},
36+
}
37+
38+
39+
for character in Character.objects.all():
40+
# Initialise cache
41+
if character.name not in cache['char']:
42+
cache['char'][character.name] = {}
43+
44+
# Skip if they have no API key defined
45+
if not character.eve_api_key:
46+
continue
47+
48+
# Get their character ID if it has never been retrieved
49+
if not character.eve_character_id:
50+
root, delta = fetch_api(CHARACTERS_URL, {}, character)
51+
err = root.find('error')
52+
if err is not None:
53+
print "ERROR %s: %s" % (err.attrib['code'], err.text)
54+
else:
55+
for row in root.findall('result/rowset/row'):
56+
if row.attrib['name'].lower() == character.name.lower():
57+
character.eve_character_id = row.attrib['characterID']
58+
character.save()
59+
60+
61+
corporation = character.corporation
62+
63+
# Initialise cache
64+
if corporation.name not in cache['corp']:
65+
cache['corp'][corporation.name] = {
66+
'balances': datetime.datetime(1900, 1, 1),
67+
'transactions': datetime.datetime(1900, 1, 1),
68+
}
69+
70+
# Update corporation wallet information/balances
71+
if _now() > cache['corp'][corporation.name]['balances']:
72+
root, delta = fetch_api(WALLET_URL, {'characterID': character.eve_character_id}, character)
73+
err = root.find('error')
74+
if err is not None:
75+
print "ERROR %s: %s" % (err.attrib['code'], err.text)
76+
else:
77+
cache['corp'][corporation.name]['balances'] = _now() + delta
78+
79+
for row in root.findall('result/rowset/row'):
80+
accountID = int(row.attrib['accountID'])
81+
accountKey = int(row.attrib['accountKey'])
82+
balance = Decimal(row.attrib['balance'])
83+
84+
wallet = CorpWallet.objects.filter(pk=accountID)
85+
if wallet:
86+
wallet[0].balance = balance
87+
else:
88+
wallet = CorpWallet(account_id=accountID, corporation=corporation, account_key=accountKey, balance=balance)
89+
wallet.save()
90+
91+
# Update corporation transactions
92+
if _now() > cache['corp'][corporation.name]['transactions']:
93+
for wallet in CorpWallet.objects.filter(corporation=corporation):
94+
# If this wallet already has some transactions, we can stop adding at the most recent one
95+
transactions = Transaction.objects.filter(corp_wallet=wallet).order_by('id')
96+
if transactions:
97+
stop_at = transactions[0].id
98+
else:
99+
stop_at = -1
100+
101+
params = {
102+
'characterID': character.eve_character_id,
103+
'accountKey': wallet.account_key,
104+
}
105+
106+
while 1:
107+
breakwhile = False
108+
109+
cache_file = 'cache/%s_%s.xml' % (corporation.id, wallet.account_key)
110+
111+
root, delta = fetch_api(TRANSACTIONS_URL, params, character)
112+
err = root.find('error')
113+
if err is not None:
114+
# Delay until later
115+
if err.attrib['code'] == '101':
116+
root = ET.fromstring(open(cache_file).read())
117+
else:
118+
print "ERROR %s: %s" % (err.attrib['code'], err.text)
119+
break
120+
else:
121+
open(cache_file, 'w').write(ET.tostring(root))
122+
123+
#<row transactionDateTime="2008-08-04 22:01:00" transactionID="705664738"
124+
# quantity="50000" typeName="Oxygen Isotopes" typeID="17887" price="250.00"
125+
# clientID="174312871" clientName="ACHAR" characterID="000000000"
126+
# characterName="SELLER" stationID="60004375"
127+
# stationName="SYSTEM IV - Moon 10 - Corporate Police Force Testing Facilities"
128+
# transactionType="buy" transactionFor="corporation"/>
129+
rows = root.findall('result/rowset/row')
130+
if not rows:
131+
break
132+
133+
for row in rows:
134+
# Skip already seen transactions
135+
transaction_id = int(row.attrib['transactionID'])
136+
if Transaction.objects.filter(pk=transaction_id):
137+
continue
138+
139+
# Make the station object if it doesn't already exist
140+
station_id = int(row.attrib['stationID'])
141+
station = Station.objects.filter(pk=station_id)
142+
if station:
143+
station = station[0]
144+
else:
145+
station = Station(id=station_id, name=row.attrib['stationName'])
146+
station.save()
147+
148+
# Make the transaction object
149+
t = Transaction(
150+
id=int(row.attrib['transactionID']),
151+
corporation=corporation,
152+
corp_wallet=wallet,
153+
date=parse_api_date(row.attrib['transactionDateTime']),
154+
t_type=row.attrib['transactionType'][0].upper(),
155+
item=Item.objects.filter(pk=row.attrib['typeID'])[0],
156+
quantity=int(row.attrib['quantity']),
157+
price=Decimal(row.attrib['price']),
158+
station=station,
159+
)
160+
t.save()
161+
162+
print t.id, t.date, t.t_type, t.item, t.quantity, t.price
163+
164+
# If we got 1000 rows we should retrieve some more
165+
if len(rows) == 1000:
166+
params['beforeTransID'] = t.id
167+
else:
168+
breakwhile = True
169+
170+
if breakwhile:
171+
break
172+
173+
cache['corp'][corporation.name]['transactions'] = _now() + delta
174+
175+
# Save cache
176+
cPickle.dump(cache, open(cache_filepath, 'wb'))
177+
178+
179+
def fetch_api(url, params, character):
180+
params['userID'] = character.eve_user_id
181+
params['apiKey'] = character.eve_api_key
182+
183+
f = urllib2.urlopen(url, urlencode(params))
184+
data = f.read()
185+
f.close()
186+
open('data.txt', 'w').write(data)
187+
root = ET.fromstring(data)
188+
current = parse_api_date(root.find('currentTime').text)
189+
until = parse_api_date(root.find('cachedUntil').text)
190+
191+
return (root, until - current)
192+
193+
def parse_api_date(s):
194+
return datetime.datetime.strptime(s, '%Y-%m-%d %H:%M:%S')
195+
196+
197+
if __name__ == '__main__':
198+
main()

cache/blank

Whitespace-only changes.

rdi/sql/corporation.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
INSERT INTO rdi_corporation (id, name) VALUES (751993277, 'Rubber Ducky Space Industries');
2+
INSERT INTO rdi_corporation (id, name) VALUES (363368013, 'Eighty Joule Brewery');
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{% extends "base.html" %}
2+
3+
{% block title %}Rubber Ducky Space Industries: Blueprint Details{% endblock %}
4+
5+
{% block content %}
6+
<h1>{{ blueprint_name }}</h1>
7+
8+
<table>
9+
<tr>
10+
<th>Item</th>
11+
<th>#</th>
12+
<th>Unit (Buy)</th>
13+
<th>Total (Buy)</th>
14+
<th>Unit (Sell)</th>
15+
<th>Total (Sell)</th>
16+
</tr>
17+
{% for component in components %}
18+
<tr class="{% cycle 'odd' 'even' %}">
19+
<td>{{ component.name }}</td>
20+
<td align="right">{{ component.count }}</td>
21+
<td align="right">{{ component.buy_median }}</td>
22+
<td align="right">{{ component.buy_total }}</td>
23+
<td align="right">{{ component.sell_median }}</td>
24+
<td align="right">{{ component.sell_total }}</td>
25+
</tr>
26+
{% endfor %}
27+
<tr>
28+
<td colspan="2"></td>
29+
<td colspan="2" align="right">{{ buy_total }}</td>
30+
<td colspan="2" align="right">{{ sell_total }}</td>
31+
</tr>
32+
</table>
33+
{% endblock %}

templates/rdi/blueprints.html

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{% extends "base.html" %}
2+
3+
{% block title %}Rubber Ducky Space Industries: Blueprints{% endblock %}
4+
5+
{% block content %}
6+
{% if bpis %}
7+
<form action="/blueprints/" method="GET">
8+
<table>
9+
<tr>
10+
<td>Runs :</td>
11+
<td><input type="text" name="runs" value="{{ runs }}"></td>
12+
<td><input type="submit" value="Go"></td>
13+
</tr>
14+
</table>
15+
</form>
16+
17+
<table>
18+
<tr>
19+
<th>Owner</th>
20+
<th>Blueprint</th>
21+
<th>ML</th>
22+
<th>PL</th>
23+
<th>#</th>
24+
<th>Time</th>
25+
<th>Unit (Buy)</th>
26+
<th>Unit (Sell)</th>
27+
<th>Market Price</th>
28+
<th>Jita</th>
29+
</tr>
30+
{% for bpi in bpis %}
31+
<tr class="{% cycle 'odd' 'even' %}">
32+
<td>{{ bpi.character }}</td>
33+
<td><a href="{{ bpi.id }}">{{ bpi.blueprint }}</a></td>
34+
<td align="center">{{ bpi.material_level }}</td>
35+
<td align="center">{{ bpi.productivity_level }}</td>
36+
<td align="right">{{ bpi.count }}</td>
37+
<td align="right">{{ bpi.production_time }}</td>
38+
<td align="right">{{ bpi.unit_cost_buy }}</td>
39+
<td align="right">{{ bpi.unit_cost_sell }}</td>
40+
<td align="right">{{ bpi.market_price }}</td>
41+
<td><a href="http://www.eve-central.com/home/quicklook.html?typeid={{ bpi.blueprint.item.id }}&usesystem=30000142">EC</a></td>
42+
</tr>
43+
{% endfor %}
44+
</table>
45+
{% else %}
46+
<p>No blueprint instances are available.</p>
47+
{% endif %}
48+
{% endblock %}

templates/rdi/error.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{% extends "base.html" %}
2+
3+
{% block title %}Rubber Ducky Space Industries: ERR-OR{% endblock %}
4+
5+
{% block content %}
6+
<h1>An error has occurred</h1>
7+
<p>{{ error }}</p>
8+
{% endblock %}

templates/registration/login.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{% extends "base.html" %}
2+
3+
{% block content %}
4+
5+
{% if form.errors %}
6+
<p class="error">Sorry, that's not a valid username or password</p>
7+
{% endif %}
8+
9+
<form action='.' method='post'>
10+
{% csrf_token %}
11+
<table>
12+
<tr class="odd">
13+
<td>Username:</td>
14+
<td><input type="text" name="username" value=""></td>
15+
</tr>
16+
<tr class="even">
17+
<td>Password:</td>
18+
<td><input type="password" name="password" value=""></td>
19+
</tr>
20+
<tr>
21+
<td colspan="2" align="right"><input type="submit" value="login"></td>
22+
</tr>
23+
</table>
24+
<input type="hidden" name="next" value="{{ next|escape }}" />
25+
</form>
26+
27+
{% endblock %}

0 commit comments

Comments
 (0)