diff --git a/papersurfer/papersurfer.py b/papersurfer/papersurfer.py index 8c4c7c9709a66700da3761e1dcace17ffa4af32b..03145f887c54559c27fe5e18a8af21b6d2865c10 100644 --- a/papersurfer/papersurfer.py +++ b/papersurfer/papersurfer.py @@ -45,6 +45,7 @@ class PaperDTO: year: int abstract: str doi: str + slug: str class Bibtex: @@ -95,7 +96,10 @@ class Doi: if "abstract" in info else "Abstract N/A") - return PaperDTO(author, authors, title, journal, year, abstract, doi) + slug = f"{info['author'][0]['family']}{year}" + + return PaperDTO(author, authors, title, journal, year, abstract, doi, + slug) def get_bibtex(self, doi): headers = { @@ -104,8 +108,12 @@ class Doi: return requests.get(f'http://dx.doi.org/{doi}', headers=headers).text def get_info(self, doi): - jsoncontent = self.load_doi_data(doi) - return self.parse_doi_json(jsoncontent) + try: + jsoncontent = self.load_doi_data(doi) + data = self.parse_doi_json(jsoncontent) + return data + except json.decoder.JSONDecodeError: + return None def extract_doi(self, hay): """Parse doi from string, or None if not found. @@ -188,12 +196,22 @@ class Mattermost: self.msgs = self.filter_incoming(msgs) return self.msgs + def check_doi_exits(self, doi): + doi_needle = Doi().extract_doi(doi) + msg_found = [msg for msg in self.msgs + if Doi().extract_doi(msg.doi) == doi_needle] + return bool(msg_found) + def get_filtered(self, needle): """Filter posts by needle.""" return [m for m in self.msgs if needle.lower() in m.message.lower() or needle.lower() in m.reporter.lower()] + def post(self, message): + self.mattermost.posts.create_post({"channel_id": self.channel, + "message": message}) + class PrettyButton(urwid.WidgetWrap): def __init__(self, label, on_press=None, user_data=None): @@ -247,6 +265,8 @@ class Papersurfer: exitbutton = PrettyButton(u'Exit', on_press=self.on_exit_clicked) self.exportbutton = PrettyButton(u'Export filtered list as bibtex', on_press=self.on_export_clicked) + submitbutton = PrettyButton('Submit paper', + on_press=self.open_submit_paper) div = urwid.Divider(u'-') self.mtm = Mattermost(url, channel, username, password) @@ -256,9 +276,14 @@ class Papersurfer: paperlist = urwid.BoxAdapter(urwid.ListBox(self.listcontent), self.size[1] - 5) - pile = urwid.Pile([ask, div, paperlist, div, - urwid.Columns([exitbutton, self.exportbutton])]) - self.top = urwid.Filler(pile, valign='middle') + buttonrow = urwid.Columns([exitbutton, self.exportbutton, + submitbutton]) + self.pile = urwid.Pile([ask, + div, + paperlist, + div, + buttonrow]) + self.top = urwid.Filler(self.pile, valign='middle') self._pile = urwid.Pile( [ self.loading_indicator() @@ -274,13 +299,12 @@ class Papersurfer: ) urwid.connect_signal(ask, 'change', self.onchange) - self.main = pile self.mainloop = urwid.MainLoop(self._over, self._palette, - unhandled_input=self.h_input ) + unhandled_input=self.h_unhandled_input) self.mainloop.set_alarm_in(.1, self.load_list) self.mainloop.run() - def h_input(self, key): + def h_unhandled_input(self, key): if key == "esc": raise urwid.ExitMainLoop() @@ -323,7 +347,7 @@ class Papersurfer: body = urwid.LineBox(body_padding) # Footer - footer = PrettyButton('Okay', self.close_details) + footer = PrettyButton('Okay', self.h_close_dialog) footer = urwid.GridFlow([footer], 8, 1, 1, 'center') # Layout @@ -427,9 +451,30 @@ class Papersurfer: paper = Doi().get_info(post.doi) self.mainloop.widget = self.details_popup(paper) - def close_details(self, _): + def h_close_dialog(self, _): + self.close_dialog() + + def close_dialog(self): self.mainloop.widget = self.top + def open_submit_paper(self, _): + + self._pile = urwid.Pile( + [ + PostDialog(self.mtm, close=self.h_close_dialog) + ] + ) + self._over = urwid.Overlay( + self._pile, + self.top, + align='center', + valign='middle', + width=100, + height=200 + ) + + self.mainloop.widget = self._over + def get_config_file_paths(): """Find, load and parse a config file. @@ -526,6 +571,81 @@ def parse_args(): return options.url, options.channel, options.username, options.password +class PostDialog(urwid.WidgetWrap): + """ + UI: + DOI: [ _________________] + Generated Message: + "# # # # # # # #" + + [Submit] [Close] + """ + def __init__(self, mattermost, close): + self.mattermost = mattermost + self.close = close + self.doi_input = urwid.Edit("Doi: ") + urwid.connect_signal(self.doi_input, 'change', self.h_input) + self.doi_result = urwid.Text("") + + body_pile = urwid.Pile([ + self.doi_input, + urwid.Divider(" "), + self.doi_result, + urwid.Divider(" "), + urwid.Columns([ + PrettyButton("Close", self.close), + PrettyButton("Submit", self.submit) + ]), + ]) + body_filler = urwid.Filler(body_pile, valign='top') + body_padding = urwid.Padding( + body_filler, + left=1, + right=1 + ) + body = urwid.LineBox(body_padding) + frame = urwid.Frame( + body, + header=urwid.Text("Submit new paper to list"), + ) + + self.widget = frame + + super(self.__class__, self).__init__(self.widget) + + def submit(self, _): + if not self.mattermost.check_doi_exits(self.doi): + self.mattermost.post(self.msg) + self.close(_) + + def create_mgs(self, paper): + msg = f"""\ +{paper.title} +{paper.authors} +{paper.journal} [{paper.slug}] +{Doi().get_doi_link(paper.doi)}""" + return msg + + def h_input(self, _, doi): + self.doi_result.set_text("... loading ...") + self.doi = None + self.msg = None + + if Doi().extract_doi(doi): + paper = Doi().get_info(doi) + if paper: + if self.mattermost.check_doi_exits(doi): + self.doi_result.set_text(f"{self.create_mgs(paper)} \n" + "-> Paper already posted! <-") + else: + self.doi_result.set_text(self.create_mgs(paper)) + self.doi = doi + self.msg = self.create_mgs(paper) + return + + self.doi_result.set_text("invalid doi") + + def main(): URL, CHANNEL, USERNAME, PASSWORD = parse_args() Papersurfer(URL, CHANNEL, USERNAME, PASSWORD)