/beats.py
Python | 317 lines | 257 code | 17 blank | 43 comment | 23 complexity | 8da07c4b26940e02aef105d0fded6157 MD5 | raw file
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- import sys
- import math
- import re
- import salary
- import unvisit
- import medborgarlon
- import swatch
- import mapcode
- import help
- from twisted.internet import reactor, task, defer, protocol
- from twisted.python import log
- from twisted.words.protocols import irc
- from twisted.web.client import getPage
- from twisted.application import internet, service
- from datetime import datetime
- from time import localtime, timezone
- import urllib2
- import json, requests, pprint
- import ast
- import feedparser
- import reimport
- from datetime import timedelta, date, datetime
- import bitstamp.client
- import duckduckgo
- import wolframalpha
- HOST, PORT = 'lindnet.eu.se.undermind.net', 6667
- #Settings for photo theme
- theme = ["Självporträtt","Frukost","Sött","Skor","Brevlåda","Himmel","Droppar","Ord på A", "Färg", "Ljus","Klockan 10", "Vardag", "Vitt", "Kork", "Reflektioner", "Säng", "Gammalt", "Natur", "Solglasögon", "Tak", "Solnedgång", "Dörr", "Två saker", "I hyllan", "Bubbla", "I väskan", "Leksak", "Tvätt", "Vän", "Liten", "Mjuk", "Utsikt", "Händer", "Ord", "Främling", "Klockan 15", "Middag", "Knapp", "Sol", "Gläje", "Ljud", "Glädje", "I garderoben", "Blått", "Kaffe", "Telefon", "Något nytt", "Tid", "Ord på K", "Ogillar", "I kylskåpet", "Barndom", "Is", "Natt", "Njutning", "Pengar", "Vikt", "Vardag", "Stor", "Upp", "Frukt", "Granne", "Klockan 17", "Ett leende", "Fönster", "Rött", "Gaffel", "En skylt", "Moln", "Solglasögon", "Ett hörn", "Roligt", "Nyckel", "Djur", "Namn", "Sopor", "Fötter", "Avslappning", "Kök", "Post", "I plånboken", "Trappor", "Krage", "Hår", "Flaska", "Cirkel", "Orange", "Yngre", "Fred", "Mamma", "Läsa", "Rosa", "Ovanlig", "Nummer", "I garaget", "Lukt", "Personlighet", "ICA", "Där du står", "Teknologi", "Morgon", "Hatt", "Konst", "Gult", "Nerifrån", "I luften", "Latex", "Gullig", "Ord på L", "Upptagen", "På golvet", "Köksbord", "Stol", "Öga", "Finger", "Platta", "Klockan 21", "Spegel", "Lugn", "Tandborste", "Sked", "Ute", "En", "Logga", "Blomma", "Pil", "Ansikte", "Mynt", "Redo", "Mat", "Hål", "Idag", "I fickan", "Hemma", "Hud", "Dröm", "Klocka", "Stig", "Kort", "Klockan 19", "Gömt", "Långt borta", "Ljus", "Ord på S", "Hjälte", "Tre saker", "Favorit", "Ärtor", "Känsla", "Kläder", "TV", "Fordon", "Svart", "Träd", "Tacksam", "Otrolig", "Skugga", "Oreda", "Två saker", "Silluett", "Ord på P", "Ränder", "Klockan 6", "Musik", "I din hand", "Tyst", "Upp-och-ner", "Par", "Cykel", "Ensam", "Metall", "Kniv", "Hej", "Genom", "Mjölk", "Ritual", "Förändring", "Skarp", "Lila", "På vägen", "På väggen", "Kärlek", "Ord på D", "Perspektiv", "Går", "Klockan 12", "Grönt", "Plats", "Byggd", "Horisont", "Tur", "Tystnad", "Rök", "Löv", "Kopp", "Vision", "Ny", "Sömn", "Strand", "Ett rum", "På hyllan", "Riktning", "Tröst", "Uppifrån", "Juice", "Värme", "Fotsteg", "Lök", "Fågel", "Insiprerande", "Bok", "Trä", "Ledighet", "Fin", "Rund", "Hjälp", "Tyg", "I fönstret", "Datum", "Närbild", "Brunt", "Val", "Inne", "Bortglömd", "Motljus", "Dryck", "Detalj", "Rötter", "Kall", "Orättvisa", "Mjuk", "Visp", "Långsam", "Naturlig", "Vuxen", "Ord på T", "Skörd", "Klockan 24", "Inramad", "Arg", "Gåva", "Aktivitet", "Ort", "Fel", "100 stycken", "Form", "Rutor", "Intressant", "Besök", "Fransar", "Klockan 13", "Ord på R", "Ja", "Träning", "Glas", "Lila", "Spiral", "Öppen", "Balkong", "Hjul", "Talrik", "Mörkt", "I lådan", "Vackert", "Volym", "Siffra", "Ovant", "Tapet", "Banken", "Muskel", "Söm", "Glugg", "I trädgården", "Samtycke", "Ägg", "Tillsammans", "Alla", "Sil", "Hon", "Ledsen", "I trappan", "Klockan 8", "Grått", "Flingor", "Bakom", "Jord", "Enkel", "Härlig", "Jakt", "Sladdar", "Fram", "Krok", "Magnet", "Paraply", "Ord på Å", "Cirklar", "Rufsig", "Utrymme", "Öl", "Plast", "Näsa", "Stad", "Film", "Ärr", "Öga", "Lura", "Väntan", "Ost", "Saker", "Resa", "Bläck", "Livsviktigt", "Klockan 15", "En sak", "Farlig", "Sträng", "Varm", "Ord på E", "Instrument", "Vinkel", "Kedja", "I backen", "Bröd", "Framtiden", "Kastrull", "Trist", "Majs", "Barndom", "Nål", "Imperfekt", "Klackar", "Kam", "Arbete", "Korg", "Dragkedja", "Nej", "Bak", "Pankaka", "Rätt", "Ord på V", "Matta", "El", "Hjärta", "I flaskan", "Enkel", "Stickad", "Glitter", "Transparant", "Lunch", "Han", "Tidning", "Driva", "Dubbel", "Mössa", "Lucka", "Klockan 14", "Tillbaka", "Rött", "Sång", "Telefon", "Rörelse", "Situation", "Soffa", "Rader" ,"I år"]
- epoch = date(2014,1,1)
- def str_to_class(str):
- return getattr(sys.modules[__name__], str)
- class MyFirstIRCProtocol(irc.IRCClient):
- nickname = 'beats'
- private = False
- def signedOn(self):
- # This is called once the server has acknowledged that we sent
- # both NICK and USER.
- for channel in self.factory.channels:
- self.join(channel)
- # Obviously, called when a PRIVMSG is received.
- def privmsg(self, user, channel, message):
- nick, _, host = user.partition('!')
- message = message.strip()
- if swatch.findBeats(message):
- if channel == self.nickname or self.private:
- self.private = False
- # When channel == self.nickname, the message was sent to the bot
- # directly and not to a channel. So we will answer directly too:
- d.addCallback(self._send_message, nick)
- self._send_message(swatch.beat2time(swatch.findBeats(message)), nick)
- else:
- # Otherwise, send the answer to the channel, and use the nick
- # as addressing in the message itself:
- self._send_message(swatch.beat2time(swatch.findBeats(message)), channel)
- # scan all massages for urls dn.se, expressen.se aftonbladet.se
- # then unvisit them return a formated link
- if unvisit.findURL(message):
- if channel == self.nickname or self.private:
- self.private = False
- # When channel == self.nickname, the message was sent to the bot
- # directly and not to a channel. So we will answer directly too:
- d.addCallback(self._send_message, nick)
- self._send_message(unvisit.findURL(message), nick)
- else:
- # Otherwise, send the answer to the channel, and use the nick
- # as addressing in the message itself:
- self._send_message(unvisit.findURL(message), channel)
- # Scan all massages for google maps URLS
- # return with a mapcode
- if mapcode.findGoogleMapURL(message):
- if channel == self.nickname or self.private:
- self.private = False
- # When channel == self.nickname, the message was sent to the bot
- # directly and not to a channel. So we will answer directly too:
- d.addCallback(self._send_message, nick)
- self._send_message(mapcode.findGoogleMapURL(message), nick)
- else:
- # Otherwise, send the answer to the channel, and use the nick
- # as addressing in the message itself:
- self._send_message(mapcode.findGoogleMapURL(message), channel)
-
- # Scan all massages for mapcodes (see: mapcode.com)
- # return with a google link with coordinates
- if mapcode.findMapcode(message):
- if channel == self.nickname or self.private:
- self.private = False
- # When channel == self.nickname, the message was sent to the bot
- # directly and not to a channel. So we will answer directly too:
- d.addCallback(self._send_message, nick)
- self._send_message(mapcode.findMapcode(message), nick)
- else:
- # Otherwise, send the answer to the channel, and use the nick
- # as addressing in the message itself:
- self._send_message(mapcode.findMapcode(message), channel)
- if not message.startswith('!'): # not a trigger command
- return # do nothing
- command, sep, rest = message.lstrip('!').partition(' ')
- # Get the function corresponding to the command given.
- command = command.replace("ö","o")
- func = getattr(self, 'command_' + command, None)
- # Or, if there was no function, ignore the message.
- if func is None:
- return
- # maybeDeferred will always return a Deferred. It calls func(rest), and
- # if that returned a Deferred, return that. Otherwise, return the return
- # value of the function wrapped in twisted.internet.defer.succeed. If
- # an exception was raised, wrap the traceback in
- # twisted.internet.defer.fail and return that.
- d = defer.maybeDeferred(func, rest)
- # Add callbacks to deal with whatever the command results are.
- # If the command gives error, the _show_error callback will turn the
- # error into a terse message first:
- d.addErrback(self._show_error)
- # Whatever is returned is sent back as a reply:
- if channel == self.nickname or self.private:
- self.private = False
- # When channel == self.nickname, the message was sent to the bot
- # directly and not to a channel. So we will answer directly too:
- d.addCallback(self._send_message, nick)
- else:
- # Otherwise, send the answer to the channel, and use the nick
- # as addressing in the message itself:
- d.addCallback(self._send_message, channel, nick)
- def command_reload(self, rest):
- reimport.reimport(unvisit)
- reimport.reimport(help)
- reimport.reimport(salary)
- reimport.reimport(medborgarlon)
- reimport.reimport(swatch)
- reimport.reimport(mapcode)
- def command_help(self, rest):
- self.private = True
- input = rest.replace(",",".")
- return help.section()
- def command_medborgare(self, rest):
- self.private = True
- input = rest.replace(",",".")
- if(len(input)<1):
- return """Välkommen till medborgarkontoret, här kan du registrera dig som merborgare i #kalix detta ger dig rätten till medborgarlön.
- Använd kommandot: \n !medborgare registrering [nick] [kontonummer] \n
- för att bli medborgare, ersätt kontonummer med din bitcoin-address. \n Glöm inte att betala frivillig skatt till: 14DYxibJ4hzng4T7i9oeVUc3aATymQvLtR"""
- elif(input.split()[0].upper() == 'REGISTRERING'):
- return """Välkommen till #kalix, %s \n detta personnummer kommer du kunna använda för att ändra uppgifter, random handläggare kommer att kontrollera dina uppgifter innan utbetalningar görs.""" % medborgarlon.registerCitizen(input.split()[1], input.split()[2])
- else:
- return "Felaktigt kommando"
- def command_lon(self, rest):
- return(salary.get())
- def command_calc(self, rest):
- client = wolframalpha.Client("X2AY6V-99EUWXYAAG")
- res = client.query(str(rest))
-
- return next(res.results).text.encode('utf8').replace("\\:0e3f","")
- def command_g(self, rest):
- url = 'http://ajax.googleapis.com/ajax/services/search/web?'
- params = dict(
- v='1.0',
- q=rest
- )
- data = requests.get(url=url, params=params)
- binary = data.content
- output = json.loads(binary)
- title = output['responseData']['results'][0]['titleNoFormatting'].encode('ascii', 'ignore')
- url = output['responseData']['results'][0]['url']
- rtStr = ("Google: {0} {1}".format(title, url))
- return rtStr.decode('utf8').encode('iso-8859-1')
- def command_duck(self, rest):
- return duckduckgo.get_zci(str(rest)).encode('iso-8859-1')
- def command_temp(self, rest):
- input = rest.replace(",",".")
- if(len(input)<1):
- tempKalix = "http://api.temperatur.nu/tnu_1.12.php?p=kalix&verbose&cli=2"
- feed = feedparser.parse( tempKalix )
- rtStr = "%s C i Kalix" % feed['entries'][0]['temp']
- return rtStr.decode('utf8').encode('iso-8859-1')
- if(input.split()[0].upper() == 'KALIX'):
- tempKalix = "http://api.temperatur.nu/tnu_1.12.php?p=kalix&verbose&cli=2"
- feed = feedparser.parse( tempKalix )
- rtStr = "%s C i Kalix" % feed['entries'][0]['temp']
- return rtStr.decode('utf8').encode('iso-8859-1')
- elif(input.split()[0].upper() == 'NYBORG'):
- tempKalix = "http://api.temperatur.nu/tnu_1.12.php?p=kalix-nyborg&verbose&cli=2"
- feed = feedparser.parse( tempKalix )
- rtStr = "%s C i Nyborg" % feed['entries'][0]['temp']
- return rtStr.decode('utf8').encode('iso-8859-1')
- elif(input.split()[0].upper() == 'JKPG'):
- tempKalix = "http://api.temperatur.nu/tnu_1.12.php?p=torpa&verbose&cli=2"
- feed = feedparser.parse( tempKalix )
- rtStr = "%s C i Jkpg" % feed['entries'][0]['temp']
- return rtStr.decode('utf8').encode('iso-8859-1')
- elif(input.split()[0].upper() == 'LJUNGBY'):
- tempKalix = "http://api.temperatur.nu/tnu_1.12.php?p=fjallgatan&verbose&cli=2"
- feed = feedparser.parse( tempKalix )
- rtStr = "%s C i Ljungby" % feed['entries'][0]['temp']
- return rtStr.decode('utf8').encode('iso-8859-1')
- elif(input.split()[0].upper() == 'GBG'):
- tempKalix = "http://api.temperatur.nu/tnu_1.12.php?p=goteborg_ostra&verbose&cli=2"
- feed = feedparser.parse( tempKalix )
- rtStr = "%s C i GBG" % feed['entries'][0]['temp']
- return rtStr.decode('utf8').encode('iso-8859-1')
- elif(input.split()[0].upper() == 'STHLM'):
- tempKalix = "http://api.temperatur.nu/tnu_1.12.php?p=tallkrogen&verbose&cli=2"
- feed = feedparser.parse( tempKalix )
- rtStr = "%s C i Stockholm" % feed['entries'][0]['temp']
- return rtStr.decode('utf8').encode('iso-8859-1')
- def command_beat(self, rest):
- beats = swatch.time2beat(rest)
- return beats
- def command_time(self, rest):
- beats = swatch.time2beat(rest)
- return beats
- def command_tema(self, rest):
- from datetime import date
- today = date.today()
- dtstr = rest
- if len(dtstr) == 0:
- dtstr = "idag"
- if(dtstr == "idag"):
- delta = today - epoch
- say_theme = "Dagens fototema är: %s" % theme[int(delta.days)]
- elif dtstr == "imorgon":
- delta = today - epoch
- say_theme = "Morgondagens fototema är: %s" % theme[int(delta.days)+1]
- elif dtstr == "igår":
- delta = today - epoch
- say_theme = "Gårdagens fototema var: %s" % theme[int(delta.days)-1]
- elif dtstr == "help":
- say_theme = "Parametrar: idag, igår, imorgon, t.ex: 2/12"
- else:
- dtstr = dtstr.split("/",1)
- datestr = '2014-%s-%s' % (dtstr[1], dtstr[0])
- date = datetime.strptime(datestr, '%Y-%m-%d').date()
- delta = date - epoch
- say_theme = "Fototema för %s är: %s" % (datestr, theme[int(delta.days)])
- return say_theme
- def _send_message(self, msg, target, nick=None):
- if nick:
- msg = '%s' % (msg)
- self.msg(target, msg)
- def _show_error(self, failure):
- return failure.getErrorMessage()
- def command_ping(self, rest):
- return 'Pong.'
- def command_saylater(self, rest):
- when, sep, msg = rest.partition(' ')
- when = int(when)
- d = defer.Deferred()
- # A small example of how to defer the reply from a command. callLater
- # will callback the Deferred with the reply after so many seconds.
- reactor.callLater(when, d.callback, msg)
- # Returning the Deferred here means that it'll be returned from
- # maybeDeferred in privmsg.
- return d
- def command_uptime(self,rest):
- with open('/proc/uptime', 'r') as f:
- uptime_seconds = float(f.readline().split()[0])
- uptime_string = str(timedelta(seconds = uptime_seconds))
- return uptime_string
- class MyFirstIRCFactory(protocol.ReconnectingClientFactory):
- protocol = MyFirstIRCProtocol
- channels = ['#kalix', '#minecraft', '#undermind', '#kalix-test']
- #channels = ['#kalix-test']
-
- if __name__ == '__main__':
- # This runs the program in the foreground. We tell the reactor to connect
- # over TCP using a given factory, and once the reactor is started, it will
- # open that connection.
- reactor.connectTCP(HOST, PORT, MyFirstIRCFactory())
- # Since we're running in the foreground anyway, show what's happening by
- # logging to stdout.
- log.startLogging(sys.stdout)
- # And this starts the reactor running. This call blocks until everything is
- # done, because this runs the whole twisted mainloop.
- reactor.run()
- # This runs the program in the background. __name__ is __builtin__ when you use
- # twistd -y on a python module.
- elif __name__ == '__builtin__':
- # Create a new application to which we can attach our services. twistd wants
- # an application object, which is how it knows what services should be
- # running. This simplifies startup and shutdown.
- application = service.Application('MyFirstIRCBot')
- # twisted.application.internet.TCPClient is how to make a TCP client service
- # which we can attach to the application.
- ircService = internet.TCPClient(HOST, PORT, MyFirstIRCFactory())
- ircService.setServiceParent(application)
- # twistd -y looks for a global variable in this module named 'application'.
- # Since there is one now, and it's all set up, there's nothing left to do.