From c9c7d389c45815e1b7abd7bea7dc5093a3630ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20P=C3=A9rez-Cerezo?= Date: Tue, 10 Oct 2017 11:45:50 +0200 Subject: Moved stuff to a module folder, preparing for setuptools --- backends/mathemensa.py | 49 --------------------- backends/mathemensa.yapsy-plugin | 3 -- backends/satyam.py | 38 ---------------- backends/satyam.yapsy-plugin | 3 -- backends/singh.py | 56 ------------------------ backends/singh.yapsy-plugin | 3 -- backends/studentenwerk.py | 72 ------------------------------- backends/studentenwerk.yapsy-plugin | 3 -- base.py | 52 ---------------------- bin/mensa | 33 ++++++++++++++ frontends/plain-text.py | 22 ---------- frontends/plain-text.yapsy-plugin | 3 -- mensa/__init__.py | 0 mensa/backends/base.py | 43 ++++++++++++++++++ mensa/backends/mathemensa.py | 49 +++++++++++++++++++++ mensa/backends/mathemensa.yapsy-plugin | 3 ++ mensa/backends/satyam.py | 38 ++++++++++++++++ mensa/backends/satyam.yapsy-plugin | 3 ++ mensa/backends/singh.py | 56 ++++++++++++++++++++++++ mensa/backends/singh.yapsy-plugin | 3 ++ mensa/backends/studentenwerk.py | 72 +++++++++++++++++++++++++++++++ mensa/backends/studentenwerk.yapsy-plugin | 3 ++ mensa/base.py | 59 +++++++++++++++++++++++++ mensa/frontends/plain-text.py | 23 ++++++++++ mensa/frontends/plain-text.yapsy-plugin | 3 ++ mensa/logic.py | 45 +++++++++++++++++++ run.py | 59 ------------------------- 27 files changed, 433 insertions(+), 363 deletions(-) delete mode 100644 backends/mathemensa.py delete mode 100644 backends/mathemensa.yapsy-plugin delete mode 100644 backends/satyam.py delete mode 100644 backends/satyam.yapsy-plugin delete mode 100644 backends/singh.py delete mode 100644 backends/singh.yapsy-plugin delete mode 100644 backends/studentenwerk.py delete mode 100644 backends/studentenwerk.yapsy-plugin delete mode 100644 base.py create mode 100755 bin/mensa delete mode 100644 frontends/plain-text.py delete mode 100644 frontends/plain-text.yapsy-plugin create mode 100644 mensa/__init__.py create mode 100644 mensa/backends/base.py create mode 100644 mensa/backends/mathemensa.py create mode 100644 mensa/backends/mathemensa.yapsy-plugin create mode 100644 mensa/backends/satyam.py create mode 100644 mensa/backends/satyam.yapsy-plugin create mode 100644 mensa/backends/singh.py create mode 100644 mensa/backends/singh.yapsy-plugin create mode 100644 mensa/backends/studentenwerk.py create mode 100644 mensa/backends/studentenwerk.yapsy-plugin create mode 100644 mensa/base.py create mode 100644 mensa/frontends/plain-text.py create mode 100644 mensa/frontends/plain-text.yapsy-plugin create mode 100755 mensa/logic.py delete mode 100755 run.py diff --git a/backends/mathemensa.py b/backends/mathemensa.py deleted file mode 100644 index ea0cf72..0000000 --- a/backends/mathemensa.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- - -import urllib.request, urllib.error, urllib.parse -from lxml import etree -from lxml.cssselect import CSSSelector -import re - -import xml.sax.saxutils as saxutils -import html5lib -import datetime -from base import * -from yapsy.IPlugin import IPlugin - -class Mathemensa(IPlugin) : - def register_restaurants(self) : - r = Restaurant("Mathemensa", "Mathemensa", self, "dummy") - register_restaurant(r) - - def get_food_items(self, **kwargs) : - weekdays = ["MONTAG", "DIENSTAG", "MITTWOCH", "DONNERSTAG", "FREITAG"] - weekday = datetime.datetime.today().weekday() - if weekday > 4 : - print("Error: No food today") - return "" - user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' - headers = {'User-Agent': user_agent} - - req = urllib.request.Request('http://personalkantine.personalabteilung.tu-berlin.de/', headers=headers) - response = urllib.request.urlopen(req) - the_page = response.read() - document = html5lib.parse(the_page, treebuilder="lxml") - sel = CSSSelector('.Menu__accordion') - fl = [] - for i in sel(document)[0] : - h2sel = CSSSelector('h2') - if not weekdays[weekday] in i[0].text.upper() : - continue - for k in i : - if k.tag.endswith("ul") : - for j in k : - price = j[1].text - st = str(etree.tostring(j)).split("\\n")[2].split("<")[0] - name = j[0].text + ", " + etree.fromstring("

%s

"%st).text.strip() # really extremely dirty hack - veg = 0 - - if "(v)" in name or "Gemüseplatte" in name : - veg = 1 - fl.append(Food(name, price, "Menü", veg)) - return fl diff --git a/backends/mathemensa.yapsy-plugin b/backends/mathemensa.yapsy-plugin deleted file mode 100644 index d122795..0000000 --- a/backends/mathemensa.yapsy-plugin +++ /dev/null @@ -1,3 +0,0 @@ -[Core] -Name = Mathemensa -Module = mathemensa \ No newline at end of file diff --git a/backends/satyam.py b/backends/satyam.py deleted file mode 100644 index ec488f3..0000000 --- a/backends/satyam.py +++ /dev/null @@ -1,38 +0,0 @@ -import urllib.request, urllib.error, urllib.parse -from lxml import etree -from lxml.cssselect import CSSSelector -import html5lib -from base import * -import re -import sys -from yapsy.IPlugin import IPlugin - -class Satyam(IPlugin): - def register_restaurants(self) : - r = Restaurant("Satyam", "Satyam", self, "dummy") - register_restaurant(r) - def get_food_items(self, **kwargs) : - s = sys.stderr - sys.stderr = open("/dev/null", "w") - user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' - headers = {'User-Agent': user_agent} - - req = urllib.request.Request('http://www.mysatyam.de/angebote/express-mittagstisch.html', headers=headers) - response = urllib.request.urlopen(req) - the_page = response.read() - document = html5lib.parse(the_page, treebuilder="lxml") - groupsel = CSSSelector('.news-latest-item-content') - k = etree.tostring(groupsel(document)[0]) - name = re.sub(r'<.+?>', ' ', str(k)) - name = etree.fromstring("

%s

"%name).text.strip() - name = name.replace("\\n", "") - name = " ".join(name.split()) - - name = name.replace("5,95 €", "") - sys.stderr = s - return [Food("Mittagstisch Express", "5,95 €", "Mittagstisch", 2, name[3:-1])] - - -# if __name__ == "__main__": -# food = get_food_items() -# print(formt(food)) diff --git a/backends/satyam.yapsy-plugin b/backends/satyam.yapsy-plugin deleted file mode 100644 index 59207ad..0000000 --- a/backends/satyam.yapsy-plugin +++ /dev/null @@ -1,3 +0,0 @@ -[Core] -Name = Satyam -Module = satyam \ No newline at end of file diff --git a/backends/singh.py b/backends/singh.py deleted file mode 100644 index ae8b291..0000000 --- a/backends/singh.py +++ /dev/null @@ -1,56 +0,0 @@ -import urllib.request, urllib.error, urllib.parse -from lxml import etree -from lxml.cssselect import CSSSelector -import html5lib -import re -import sys -import datetime -from base import * -from yapsy.IPlugin import IPlugin - -class Signh(IPlugin) : - def register_restaurants(self) : - r = Restaurant("Singh", "Mathe-Café", self, "dummy") - register_restaurant(r) - def get_food_items(self, **kwargs) : - s = sys.stderr - sys.stderr = open("/dev/null", "w") - weekday = datetime.datetime.today().weekday() - if weekday > 4 : - print("Error: No food today") - return "" - user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' - headers = {'User-Agent': user_agent} - - req = urllib.request.Request('http://singh-catering.de/cafe/', headers=headers) - response = urllib.request.urlopen(req) - the_page = response.read() - document = html5lib.parse(the_page, treebuilder="lxml") - groupsel = CSSSelector('.menu-list__items') - myorder=[0,3,1,4,2] - mylist = [ groupsel(document)[i] for i in myorder] - i = mylist[weekday] - fl = [] - nmsel = CSSSelector('.menu-list__item') - for k in nmsel(i): - veg = 0 - titsel = CSSSelector('.item_title') - name = titsel(k)[0].text - dscsel = CSSSelector('.desc__content') - desc = dscsel(k)[0].text - prsel = CSSSelector('.menu-list__item-price') - price = prsel(k)[0].text - vegsel = CSSSelector('.menu-list__item-highlight-title') - if len(vegsel(k)) > 0 : - if "VEGETARISCH" in vegsel(k)[0].text : - veg = 1 - elif "VEGAN" in vegsel(k)[0].text : - veg = 2 - fl.append(Food(name, price, "Essen", veg, desc)) - sys.stderr = s - return fl - -if __name__ == "__main__": - food = get_food_items() - print(formt(food)) - diff --git a/backends/singh.yapsy-plugin b/backends/singh.yapsy-plugin deleted file mode 100644 index 7faf774..0000000 --- a/backends/singh.yapsy-plugin +++ /dev/null @@ -1,3 +0,0 @@ -[Core] -Name = Mathe-Café -Module = singh \ No newline at end of file diff --git a/backends/studentenwerk.py b/backends/studentenwerk.py deleted file mode 100644 index 48b15d3..0000000 --- a/backends/studentenwerk.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (C) 2017 Gabriel Perez-Cerezo -# -*- coding: utf-8 -*- - -import urllib.request, urllib.error, urllib.parse -from lxml import etree -from lxml.cssselect import CSSSelector -import html5lib -from base import * -from yapsy.IPlugin import IPlugin -import multiprocessing - - -from yapsy import NormalizePluginNameForModuleName as normalize - -mensenliste = {"TU Hardenbergstraße" : "mensa-tu-hardenbergstra%C3%9Fe", "TU Marchstraße": "cafeteria-tu-marchstra%C3%9Fe", "TU Skyline": "cafeteria-tu-skyline", "TU Architektur": "cafeteria-tu-architektur", "TU Ackerstraße": "cafeteria-tu-ackerstra%C3%9Fe"} - - - -def pr_f(j) : - i,k = j - food = get_food_items(k, ignore_nudelauswahl=True) - return (i,"*"*20+i+"*"*20+"\n"+formt(food)) - -class Studentenwerk(IPlugin) : - def register_restaurants (self) : - mensenliste = {"TU Hardenbergstraße" : "mensa-tu-hardenbergstra%C3%9Fe", "TU Marchstraße": "cafeteria-tu-marchstra%C3%9Fe", "TU Skyline": "cafeteria-tu-skyline", "TU Architektur": "cafeteria-tu-architektur", "TU Ackerstraße": "cafeteria-tu-ackerstra%C3%9Fe"} - for h,n in mensenliste.items() : - r = Restaurant(normalize(h), h, self, "dummy", [n]) - register_restaurant(r) - def get_food_items(self, mensa="mensa-tu-hardenbergstra%C3%9Fe", ignore_nudelauswahl=False) : - user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' - headers = {'User-Agent': user_agent} - - req = urllib.request.Request('https://www.stw.berlin/mensen/%s.html' % mensa, headers=headers) - response = urllib.request.urlopen(req) - the_page = response.read() - document = html5lib.parse(the_page, treebuilder="lxml") - groupsel = CSSSelector('.splGroupWrapper') - groups = [e for e in groupsel(document)] - fl = [] - for i in groups : - try: - name = CSSSelector('.splGroup')(i)[0].text - except: - raise NoMenuError from None - sel = CSSSelector('.splMeal') - meals = [e for e in sel(i)] - for m in meals : - namesel = CSSSelector('.bold') - nm = namesel(m)[0].text - if ignore_nudelauswahl and "Nudelauswahl" in nm : - continue - pricesel = CSSSelector('.col-md-3') - veg = 0 - if len(pricesel(m)[0]) >= 2 : - if "15" in pricesel(m)[0][1].attrib["src"] : - veg = 2 - elif "1.png" in pricesel(m)[0][1].attrib["src"] : - veg = 1 - price = pricesel(m)[-1].text.strip() - fl.append(Food(nm, price, name, veg)) - return fl - - - -# format: -# if __name__ == "__main__": -# pool = multiprocessing.Pool(4) -# k = pool.map(pr_f, list(mensenliste.items())) -# k.sort(key=lambda x: x[0]) -# for i in k : -# print(i[1]) diff --git a/backends/studentenwerk.yapsy-plugin b/backends/studentenwerk.yapsy-plugin deleted file mode 100644 index ad2a994..0000000 --- a/backends/studentenwerk.yapsy-plugin +++ /dev/null @@ -1,3 +0,0 @@ -[Core] -Name = Studentenwerk -Module = studentenwerk \ No newline at end of file diff --git a/base.py b/base.py deleted file mode 100644 index df7bd4a..0000000 --- a/base.py +++ /dev/null @@ -1,52 +0,0 @@ -# Common classes and methods. - -class Food : - def __init__(self,name, price="", category="Essen", veggie=False, desc=None, ingredients={}) : - self.name = name - self.price = price - self.category = category - self.veggie = veggie - self.desc=desc - self.ingredients=ingredients - -class NoMenuError(Exception) : - """ gets raised if there's no menu""" - -class Frontend(object) : - def __init__(self, name, human_name, description="", optional_args=[]) : - self.name = name - self.human_name = human_name - self.description = description - self.optional_args = [] - -def formt (food) : - cat = [] - vegkeys = [ "", "Vegetarian", "Vegan" ] - r = "" - food.sort(key=lambda foo: foo.category) - for i in food: - if not i.category in cat : - cat.append(i.category) - if not i.category == None : - r=r+ i.category+"\n" - r=r+"\t" + i.name.ljust(80) + "\t"+ i.price.ljust(20) + vegkeys[i.veggie]+"\n" - if i.desc : - r = r+"\t "+i.desc+"\n" - return r - -foodsources = {} - -class Restaurant(object): - def __init__(self, name, human_name, module, optional_args=[], obligatory_args=()): - self.name = name - self.human_name = human_name - self.module = module - self.optional_args = optional_args - self.obligatory_args = obligatory_args - - def get_food(self,**opt_args) : - return self.module.get_food_items(*self.obligatory_args, **opt_args) - -def register_restaurant(restaurant): - global foodsources - foodsources[restaurant.name] = (restaurant) diff --git a/bin/mensa b/bin/mensa new file mode 100755 index 0000000..b141990 --- /dev/null +++ b/bin/mensa @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +import argparse +from mensa import logic +from mensa import base + +parser = argparse.ArgumentParser(description='Fetch menus from various sources') +# parser.add_argument('integers', metavar='N', type=int, nargs='+', +# help='an integer for the accumulator') +parser.add_argument('-r', '--restaurants', dest='rest', action='store', + metavar='LIST', + help='Comma-separated list of restaurants to fetch the menus from.') +parser.add_argument('-l', '--list-restaurants', dest='list', action='store_true', + help='get list of restaurants') + + +args = parser.parse_args() +## Load backends +logic.init_foodsources() +## Load frontends (not yet implemented) +logic.init_renderers() + + + +if args.list : + for k,i in base.foodsources.items(): + print(i.name, i.human_name) + exit() +restlist = None +if args.rest : + restlist = args.rest.split(",") + +foodl = logic.get_food(restlist) +logic.render(foodl, ["plain-text"]) diff --git a/frontends/plain-text.py b/frontends/plain-text.py deleted file mode 100644 index 71cbf42..0000000 --- a/frontends/plain-text.py +++ /dev/null @@ -1,22 +0,0 @@ -import base -from yapsy.IPlugin import IPlugin -class TextRenderer(IPlugin) : - def render (self, foods, **options) : - ## Expects list of tuples with (Restaurant, Foodlist) - r = "" - vegkeys = [ "", "Vegetarian", "Vegan" ] - for restaurant, food in foods : - cat = [] - r = r+"*"*20+restaurant.human_name+"*"*20+"\n"#+base.formt(food) - food.sort(key=lambda foo: foo.category) - for i in food: - if not i.category in cat : - cat.append(i.category) - if not i.category == None : - r=r+ i.category+"\n" - r=r+"\t" + i.name.ljust(80) + "\t"+ i.price.ljust(20) + vegkeys[i.veggie]+"\n" - if i.desc : - r = r+"\t "+i.desc+"\n" - print(r) - - diff --git a/frontends/plain-text.yapsy-plugin b/frontends/plain-text.yapsy-plugin deleted file mode 100644 index 103cdc4..0000000 --- a/frontends/plain-text.yapsy-plugin +++ /dev/null @@ -1,3 +0,0 @@ -[Core] -Name = Plain Text Output -Module = plain-text \ No newline at end of file diff --git a/mensa/__init__.py b/mensa/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mensa/backends/base.py b/mensa/backends/base.py new file mode 100644 index 0000000..6c57336 --- /dev/null +++ b/mensa/backends/base.py @@ -0,0 +1,43 @@ +# Common classes and methods. + +class Food : + def __init__(self,name, price="", category="Essen", veggie=False, desc=None, ingredients={}) : + self.name = name + self.price = price + self.category = category + self.veggie = veggie + self.desc=desc + self.ingredients=ingredients + +def formt (food) : + cat = [] + vegkeys = [ "", "Vegetarian", "Vegan" ] + r = "" + food.sort(key=lambda foo: foo.category) + for i in food: + if not i.category in cat : + cat.append(i.category) + if not i.category == None : + r=r+ i.category+"\n" + r=r+"\t" + i.name.ljust(80) + "\t"+ i.price.ljust(20) + vegkeys[i.veggie]+"\n" + if i.desc : + r = r+"\t "+i.desc+"\n" + return r + +foodsources = {} + +class Restaurant(object): + def __init__(self, name, human_name, module, optional_args=[], obligatory_args=()): + self.name = name + self.human_name = human_name + self.module = module + self.optional_args = optional_args + self.obligatory_args = obligatory_args + + def get_food(**opt_args) : + self.module.get_food_items(*obligatory_args, **optional_args) + + +def register_restaurant(restaurant): + global foodsources + foodsources[restaurant.name] = (restaurant) diff --git a/mensa/backends/mathemensa.py b/mensa/backends/mathemensa.py new file mode 100644 index 0000000..8f66805 --- /dev/null +++ b/mensa/backends/mathemensa.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +import urllib.request, urllib.error, urllib.parse +from lxml import etree +from lxml.cssselect import CSSSelector +import re + +import xml.sax.saxutils as saxutils +import html5lib +import datetime +from mensa.base import * +from yapsy.IPlugin import IPlugin + +class Mathemensa(IPlugin) : + def register_restaurants(self) : + r = Restaurant("Mathemensa", "Mathemensa", self, "dummy") + register_restaurant(r) + + def get_food_items(self, **kwargs) : + weekdays = ["MONTAG", "DIENSTAG", "MITTWOCH", "DONNERSTAG", "FREITAG"] + weekday = datetime.datetime.today().weekday() + if weekday > 4 : + print("Error: No food today") + return "" + user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' + headers = {'User-Agent': user_agent} + + req = urllib.request.Request('http://personalkantine.personalabteilung.tu-berlin.de/', headers=headers) + response = urllib.request.urlopen(req) + the_page = response.read() + document = html5lib.parse(the_page, treebuilder="lxml") + sel = CSSSelector('.Menu__accordion') + fl = [] + for i in sel(document)[0] : + h2sel = CSSSelector('h2') + if not weekdays[weekday] in i[0].text.upper() : + continue + for k in i : + if k.tag.endswith("ul") : + for j in k : + price = j[1].text + st = str(etree.tostring(j)).split("\\n")[2].split("<")[0] + name = j[0].text + ", " + etree.fromstring("

%s

"%st).text.strip() # really extremely dirty hack + veg = 0 + + if "(v)" in name or "Gemüseplatte" in name : + veg = 1 + fl.append(Food(name, price, "Menü", veg)) + return fl diff --git a/mensa/backends/mathemensa.yapsy-plugin b/mensa/backends/mathemensa.yapsy-plugin new file mode 100644 index 0000000..d122795 --- /dev/null +++ b/mensa/backends/mathemensa.yapsy-plugin @@ -0,0 +1,3 @@ +[Core] +Name = Mathemensa +Module = mathemensa \ No newline at end of file diff --git a/mensa/backends/satyam.py b/mensa/backends/satyam.py new file mode 100644 index 0000000..7ac53a0 --- /dev/null +++ b/mensa/backends/satyam.py @@ -0,0 +1,38 @@ +import urllib.request, urllib.error, urllib.parse +from lxml import etree +from lxml.cssselect import CSSSelector +import html5lib +from mensa.base import * +import re +import sys +from yapsy.IPlugin import IPlugin + +class Satyam(IPlugin): + def register_restaurants(self) : + r = Restaurant("Satyam", "Satyam", self, "dummy") + register_restaurant(r) + def get_food_items(self, **kwargs) : + s = sys.stderr + sys.stderr = open("/dev/null", "w") + user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' + headers = {'User-Agent': user_agent} + + req = urllib.request.Request('http://www.mysatyam.de/angebote/express-mittagstisch.html', headers=headers) + response = urllib.request.urlopen(req) + the_page = response.read() + document = html5lib.parse(the_page, treebuilder="lxml") + groupsel = CSSSelector('.news-latest-item-content') + k = etree.tostring(groupsel(document)[0]) + name = re.sub(r'<.+?>', ' ', str(k)) + name = etree.fromstring("

%s

"%name).text.strip() + name = name.replace("\\n", "") + name = " ".join(name.split()) + + name = name.replace("5,95 €", "") + sys.stderr = s + return [Food("Mittagstisch Express", "5,95 €", "Mittagstisch", 2, name[3:-1])] + + +# if __name__ == "__main__": +# food = get_food_items() +# print(formt(food)) diff --git a/mensa/backends/satyam.yapsy-plugin b/mensa/backends/satyam.yapsy-plugin new file mode 100644 index 0000000..59207ad --- /dev/null +++ b/mensa/backends/satyam.yapsy-plugin @@ -0,0 +1,3 @@ +[Core] +Name = Satyam +Module = satyam \ No newline at end of file diff --git a/mensa/backends/singh.py b/mensa/backends/singh.py new file mode 100644 index 0000000..844cc9c --- /dev/null +++ b/mensa/backends/singh.py @@ -0,0 +1,56 @@ +import urllib.request, urllib.error, urllib.parse +from lxml import etree +from lxml.cssselect import CSSSelector +import html5lib +import re +import sys +import datetime +from mensa.base import * +from yapsy.IPlugin import IPlugin + +class Signh(IPlugin) : + def register_restaurants(self) : + r = Restaurant("Singh", "Mathe-Café", self, "dummy") + register_restaurant(r) + def get_food_items(self, **kwargs) : + s = sys.stderr + sys.stderr = open("/dev/null", "w") + weekday = datetime.datetime.today().weekday() + if weekday > 4 : + print("Error: No food today") + return "" + user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' + headers = {'User-Agent': user_agent} + + req = urllib.request.Request('http://singh-catering.de/cafe/', headers=headers) + response = urllib.request.urlopen(req) + the_page = response.read() + document = html5lib.parse(the_page, treebuilder="lxml") + groupsel = CSSSelector('.menu-list__items') + myorder=[0,3,1,4,2] + mylist = [ groupsel(document)[i] for i in myorder] + i = mylist[weekday] + fl = [] + nmsel = CSSSelector('.menu-list__item') + for k in nmsel(i): + veg = 0 + titsel = CSSSelector('.item_title') + name = titsel(k)[0].text + dscsel = CSSSelector('.desc__content') + desc = dscsel(k)[0].text + prsel = CSSSelector('.menu-list__item-price') + price = prsel(k)[0].text + vegsel = CSSSelector('.menu-list__item-highlight-title') + if len(vegsel(k)) > 0 : + if "VEGETARISCH" in vegsel(k)[0].text : + veg = 1 + elif "VEGAN" in vegsel(k)[0].text : + veg = 2 + fl.append(Food(name, price, "Essen", veg, desc)) + sys.stderr = s + return fl + +if __name__ == "__main__": + food = get_food_items() + print(formt(food)) + diff --git a/mensa/backends/singh.yapsy-plugin b/mensa/backends/singh.yapsy-plugin new file mode 100644 index 0000000..7faf774 --- /dev/null +++ b/mensa/backends/singh.yapsy-plugin @@ -0,0 +1,3 @@ +[Core] +Name = Mathe-Café +Module = singh \ No newline at end of file diff --git a/mensa/backends/studentenwerk.py b/mensa/backends/studentenwerk.py new file mode 100644 index 0000000..a8f6c2b --- /dev/null +++ b/mensa/backends/studentenwerk.py @@ -0,0 +1,72 @@ +# Copyright (C) 2017 Gabriel Perez-Cerezo +# -*- coding: utf-8 -*- + +import urllib.request, urllib.error, urllib.parse +from lxml import etree +from lxml.cssselect import CSSSelector +import html5lib +from mensa.base import * +from yapsy.IPlugin import IPlugin +import multiprocessing + + +from yapsy import NormalizePluginNameForModuleName as normalize + +mensenliste = {"TU Hardenbergstraße" : "mensa-tu-hardenbergstra%C3%9Fe", "TU Marchstraße": "cafeteria-tu-marchstra%C3%9Fe", "TU Skyline": "cafeteria-tu-skyline", "TU Architektur": "cafeteria-tu-architektur", "TU Ackerstraße": "cafeteria-tu-ackerstra%C3%9Fe"} + + + +def pr_f(j) : + i,k = j + food = get_food_items(k, ignore_nudelauswahl=True) + return (i,"*"*20+i+"*"*20+"\n"+formt(food)) + +class Studentenwerk(IPlugin) : + def register_restaurants (self) : + mensenliste = {"TU Hardenbergstraße" : "mensa-tu-hardenbergstra%C3%9Fe", "TU Marchstraße": "cafeteria-tu-marchstra%C3%9Fe", "TU Skyline": "cafeteria-tu-skyline", "TU Architektur": "cafeteria-tu-architektur", "TU Ackerstraße": "cafeteria-tu-ackerstra%C3%9Fe"} + for h,n in mensenliste.items() : + r = Restaurant(normalize(h), h, self, "dummy", [n]) + register_restaurant(r) + def get_food_items(self, mensa="mensa-tu-hardenbergstra%C3%9Fe", ignore_nudelauswahl=False) : + user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' + headers = {'User-Agent': user_agent} + + req = urllib.request.Request('https://www.stw.berlin/mensen/%s.html' % mensa, headers=headers) + response = urllib.request.urlopen(req) + the_page = response.read() + document = html5lib.parse(the_page, treebuilder="lxml") + groupsel = CSSSelector('.splGroupWrapper') + groups = [e for e in groupsel(document)] + fl = [] + for i in groups : + try: + name = CSSSelector('.splGroup')(i)[0].text + except: + raise NoMenuError from None + sel = CSSSelector('.splMeal') + meals = [e for e in sel(i)] + for m in meals : + namesel = CSSSelector('.bold') + nm = namesel(m)[0].text + if ignore_nudelauswahl and "Nudelauswahl" in nm : + continue + pricesel = CSSSelector('.col-md-3') + veg = 0 + if len(pricesel(m)[0]) >= 2 : + if "15" in pricesel(m)[0][1].attrib["src"] : + veg = 2 + elif "1.png" in pricesel(m)[0][1].attrib["src"] : + veg = 1 + price = pricesel(m)[-1].text.strip() + fl.append(Food(nm, price, name, veg)) + return fl + + + +# format: +# if __name__ == "__main__": +# pool = multiprocessing.Pool(4) +# k = pool.map(pr_f, list(mensenliste.items())) +# k.sort(key=lambda x: x[0]) +# for i in k : +# print(i[1]) diff --git a/mensa/backends/studentenwerk.yapsy-plugin b/mensa/backends/studentenwerk.yapsy-plugin new file mode 100644 index 0000000..ad2a994 --- /dev/null +++ b/mensa/backends/studentenwerk.yapsy-plugin @@ -0,0 +1,3 @@ +[Core] +Name = Studentenwerk +Module = studentenwerk \ No newline at end of file diff --git a/mensa/base.py b/mensa/base.py new file mode 100644 index 0000000..fa7346a --- /dev/null +++ b/mensa/base.py @@ -0,0 +1,59 @@ +# This file contains functions and classes necessary for the operation of backends. + +class Food : + def __init__(self,name, price="", category="Essen", veggie=False, desc=None, ingredients={}) : + self.name = name + self.price = price + self.category = category + self.veggie = veggie + self.desc=desc + self.ingredients=ingredients + +class NoMenuError(Exception) : + """ gets raised if there's no menu""" + +class Renderer(object) : + def __init__(self, name, human_name, module, description="", optional_args=[]) : + self.name = name + self.human_name = human_name + self.description = description + self.optional_args = [] + self.module = module + def render(self, foods, **options) : + self.module.render(foods, **options) + +def formt (food) : + cat = [] + vegkeys = [ "", "Vegetarian", "Vegan" ] + r = "" + food.sort(key=lambda foo: foo.category) + for i in food: + if not i.category in cat : + cat.append(i.category) + if not i.category == None : + r=r+ i.category+"\n" + r=r+"\t" + i.name.ljust(80) + "\t"+ i.price.ljust(20) + vegkeys[i.veggie]+"\n" + if i.desc : + r = r+"\t "+i.desc+"\n" + return r + +foodsources = {} +renderers = {} + +class Restaurant(object): + def __init__(self, name, human_name, module, optional_args=[], obligatory_args=()): + self.name = name + self.human_name = human_name + self.module = module + self.optional_args = optional_args + self.obligatory_args = obligatory_args + + def get_food(self,**opt_args) : + return self.module.get_food_items(*self.obligatory_args, **opt_args) + +def register_restaurant(restaurant): + global foodsources + foodsources[restaurant.name] = restaurant +def register_renderer(renderer) : + global renderers + renderers[renderer.name] = renderer diff --git a/mensa/frontends/plain-text.py b/mensa/frontends/plain-text.py new file mode 100644 index 0000000..501be54 --- /dev/null +++ b/mensa/frontends/plain-text.py @@ -0,0 +1,23 @@ +from mensa import base +from yapsy.IPlugin import IPlugin +class TextRenderer(IPlugin) : + def render (self, foods, **options) : + ## Expects list of tuples with (Restaurant, Foodlist) + r = "" + vegkeys = [ "", "Vegetarian", "Vegan" ] + for restaurant, food in foods : + cat = [] + r = r+"*"*20+restaurant.human_name+"*"*20+"\n"#+base.formt(food) + food.sort(key=lambda foo: foo.category) + for i in food: + if not i.category in cat : + cat.append(i.category) + if not i.category == None : + r=r+ i.category+"\n" + r=r+"\t" + i.name.ljust(80) + "\t"+ i.price.ljust(20) + vegkeys[i.veggie]+"\n" + if i.desc : + r = r+"\t "+i.desc+"\n" + print(r) + + def register_renderer(self) : + base.register_renderer(base.Renderer("plain-text", "Plain Text Renderer", self)) diff --git a/mensa/frontends/plain-text.yapsy-plugin b/mensa/frontends/plain-text.yapsy-plugin new file mode 100644 index 0000000..103cdc4 --- /dev/null +++ b/mensa/frontends/plain-text.yapsy-plugin @@ -0,0 +1,3 @@ +[Core] +Name = Plain Text Output +Module = plain-text \ No newline at end of file diff --git a/mensa/logic.py b/mensa/logic.py new file mode 100755 index 0000000..b0165f0 --- /dev/null +++ b/mensa/logic.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 + +from mensa import base +import urllib.error +import os +from yapsy.PluginManager import PluginManager + + +def init_foodsources(): + backends = PluginManager() + backends.setPluginPlaces([os.path.join(os.path.dirname(os.path.realpath(__file__)),"backends")]) + backends.collectPlugins() + for pluginInfo in backends.getAllPlugins(): + backends.activatePluginByName(pluginInfo.name) + pluginInfo.plugin_object.register_restaurants() + +def init_renderers(): + frontends = PluginManager() + frontends.setPluginPlaces([os.path.join(os.path.dirname(os.path.realpath(__file__)),"frontends")]) + frontends.collectPlugins() + for pluginInfo in frontends.getAllPlugins(): + frontends.activatePluginByName(pluginInfo.name) + pluginInfo.plugin_object.register_renderer() + + +def get_food(restlist=False, options={}) : + foodl = [] + for k,i in base.foodsources.items() : + if restlist and not i.name in restlist : + continue + try : + food = i.get_food(ignore_nudelauswahl=True) + foodl.append((i, food)) + # print("*"*20+i.human_name+"*"*20+"\n"+base.formt(food)) + except base.NoMenuError: + print(i.human_name + ": No menu found. This could be due to a holiday or due to an error in the script.") + except urllib.error.HTTPError as e : + print(i.human_name + ": Fetching menu failed: %s" % str(e)) + return foodl + +def render(to_render, rendlist=False, options={}) : + for k,i in base.renderers.items() : + if rendlist and not i.name in rendlist : + continue + i.render(to_render) diff --git a/run.py b/run.py deleted file mode 100755 index a4248d5..0000000 --- a/run.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python3 - -import base -import urllib.error - -import argparse - -parser = argparse.ArgumentParser(description='Fetch menus from various sources') -# parser.add_argument('integers', metavar='N', type=int, nargs='+', -# help='an integer for the accumulator') -parser.add_argument('-r', '--restaurants', dest='rest', action='store', - metavar='LIST', - help='Comma-separated list of restaurants to fetch the menus from.') -parser.add_argument('-l', '--list-restaurants', dest='list', action='store_true', - help='get list of restaurants') - - -args = parser.parse_args() -## Load backends -from yapsy.PluginManager import PluginManager -backends = PluginManager() -backends.setPluginPlaces(["./backends"]) -backends.collectPlugins() -## Load frontends (not yet implemented) -from yapsy.PluginManager import PluginManager -frontends = PluginManager() -frontends.setPluginPlaces(["./frontends"]) -frontends.collectPlugins() - -for pluginInfo in backends.getAllPlugins(): - backends.activatePluginByName(pluginInfo.name) - pluginInfo.plugin_object.register_restaurants() -for pluginInfo in frontends.getAllPlugins(): - frontends.activatePluginByName(pluginInfo.name) - - -if args.list : - for k,i in base.foodsources.items(): - print(i.name, i.human_name) - exit() -restlist = None -if args.rest : - restlist = args.rest.split(",") -to_render = [] -for k,i in base.foodsources.items() : - if restlist and not i.name in restlist : - continue - try : - food = i.get_food(ignore_nudelauswahl=True) - to_render.append((i, food)) - # print("*"*20+i.human_name+"*"*20+"\n"+base.formt(food)) - except base.NoMenuError: - print(i.human_name + ": No menu found. This could be due to a holiday or due to an error in the script.") - except urllib.error.HTTPError as e : - print(i.human_name + ": Fetching menu failed: %s" % str(e)) - -for i in frontends.getAllPlugins(): - print(i.name) - i.plugin_object.render(to_render) -- cgit v1.2.3