123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- """
- Copyright 2015, Joseph Botosh <rumly111@gmail.com>
- This file is part of tradey, a trading bot in The Mana World
- see www.themanaworld.org
- 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.
- You should have received a copy of the GNU General Public License along with
- this program. If not, see <http://www.gnu.org/licenses/>.
- Additionally to the GPL, you are *strongly* encouraged to share any modifications
- you do on these sources.
- """
- import sys
- import logging
- import urllib2
- import string
- import sqlite3
- import datetime
- import threading
- import time
- from net.packet_out import whisper
- import config
- class OnlineUsers:
- def __init__(self, online_url='http://server.themanaworld.org/online-old.txt', update_interval=20):
- self._active = False
- self._timer = 0
- self._thread = threading.Thread(target=self._threadfunc, args=())
- self._url = online_url
- self._update_interval = update_interval
- self.__lock = threading.Lock()
- self.__online_users = []
- @property
- def online_users(self):
- self.__lock.acquire(True)
- users = self.__online_users[:]
- self.__lock.release()
- return users
- def dl_online_list(self):
- """
- Download online.txt, parse it, and return a list of online user nicks.
- If error occurs, return empty list
- """
- try:
- data = urllib2.urlopen(self._url).read()
- except urllib2.URLError, e:
- # self.logger.error("urllib error: %s", e.message)
- print ("urllib error: %s" % e.message)
- return []
- start = string.find(data, '------------------------------\n') + 31
- end = string.rfind(data, '\n\n')
- s = data[start:end]
- return map(lambda n: n[:-5].strip() if n.endswith('(GM) ') else n.strip(),
- s.split('\n'))
- def _threadfunc(self):
- while self._active:
- if (time.time() - self._timer) > self._update_interval:
- users = self.dl_online_list()
- self.__lock.acquire(True)
- self.__online_users=users
- self.__lock.release()
- self._timer = time.time()
- else:
- time.sleep(1.0)
- def start(self):
- self._active = True
- self._thread.start()
- def stop(self):
- if self._active:
- self._active = False
- self._thread.join()
- class SqliteDbManager:
- def __init__(self, dbfile):
- self._active = False
- self._timer = 0
- self._lastseen_thread = threading.Thread(target=self.__lastseen_threadfunc, args=())
- self._mailbox_thread = threading.Thread(target=self.__mailbox_threadfunc, args=())
- self._dbfile = dbfile
- self.mapserv = None
- self._online_manager = OnlineUsers(config.online_txt_url, config.online_txt_interval)
- self.db, self.cur = self._open_sqlite_db(dbfile)
- self.cur.execute('create table if not exists LastSeen(\
- NICK text[25] not null unique,\
- DATE_ date not null)')
- self.cur.execute('create table if not exists MailBox(\
- ID integer primary key,\
- FROM_ text[25] not null,\
- TO_ text[25] not null,\
- MESSAGE text[255] not null)')
- self.cur.execute('create unique index if not exists \
- FROM_TO_IDX on MailBox(FROM_,TO_)')
- self.db.commit()
- def __del__(self):
- try:
- self.db.close()
- except Exception:
- pass
- def _open_sqlite_db(self, dbfile):
- """
- Open sqlite db, and return tuple (connection, cursor)
- """
- try:
- db = sqlite3.connect(dbfile)
- cur = db.cursor()
- except sqlite3.Error, e:
- # self.logger.error("sqlite3 error: %s", e.message)
- print ("sqlite3 error: %s" % e.message)
- sys.exit(1)
- return db, cur
- def __update_lastseen_info(self, users, db, cur):
- now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
- values = map(lambda u: (u, now), users)
- cur.executemany('replace into LastSeen(NICK,DATE_) values(?,?)',
- values)
- db.commit()
- def get_lastseen_info(self, nick):
- try:
- self.cur.execute('select DATE_ from LastSeen where NICK=?',(nick,))
- self.db.commit() # NOTE: do I need it?
- row = self.cur.fetchone()
- except sqlite3.Error, e:
- print ("sqlite3 error: %s" % e.message)
- row = ["although I do not remember when."]
- if row:
- return ('%s was seen %s' % (nick, row[0])).encode('utf-8')
- else:
- return '%s was never seen' % nick
- def __lastseen_threadfunc(self):
- print '__lastseen_threadfunc started'
- db, cur = self._open_sqlite_db(self._dbfile)
- while self._active:
- if (time.time() - self._timer) > 60:
- users = self._online_manager.online_users
- self.__update_lastseen_info(users, db, cur)
- self._timer = time.time()
- else:
- time.sleep(1.0)
- db.close()
- def send_mail(self, from_, to_, message):
- try:
- self.cur.execute('replace into MailBox(FROM_,TO_,MESSAGE) values(?,?,?)',
- (from_,to_,message))
- self.db.commit()
- except sqlite3.Error, e:
- print ("sqlite3 error: %s" % e.message)
- def get_unread_mails(self, nick, db=None, cur=None):
- try:
- if db is None:
- db = self.db
- if cur is None:
- cur = self.cur
- cur.execute('select FROM_,MESSAGE from MailBox where TO_=?',
- (nick,))
- db.commit()
- mails = cur.fetchall()
- cur.execute('delete from MailBox where TO_=?',
- (nick,))
- db.commit()
- except sqlite3.Error, e:
- print ("sqlite3 error: %s" % e.message)
- mails = []
- return mails
- def __mailbox_threadfunc(self):
- print '__mailbox_threadfunc started'
- db, cur = self._open_sqlite_db(self._dbfile)
- while self._active:
- if (time.time() - self._timer) > 60:
- users = self._online_manager.online_users
- for u in users:
- mail = self.get_unread_mails(u, db, cur)
- nm = len(mail)
- if nm > 0:
- self.mapserv.sendall(whisper(u, "You have %d new mails:" % (nm,)))
- time.sleep(0.7)
- for m in mail:
- msg = ("From %s : %s" % (m[0], m[1])).encode('utf-8')
- self.mapserv.sendall(whisper(u, msg))
- time.sleep(0.7)
- self._timer = time.time()
- else:
- time.sleep(1.0)
- db.close()
- def forEachOnline(self, callback, *args):
- users = self._online_manager.online_users
- for u in users:
- callback(u, *args)
- def start(self):
- self._online_manager.start()
- self._active = True
- self._lastseen_thread.start()
- self._mailbox_thread.start()
- def stop(self):
- if self._active:
- self._active = False
- self._lastseen_thread.join()
- self._mailbox_thread.join()
- self._online_manager.stop()
- if __name__=='__main__':
- print "You should not run this file. Use main.py"
|