diff --git a/telegram_export/formatters/baseformatter.py b/telegram_export/formatters/baseformatter.py index 043c01d..782e370 100644 --- a/telegram_export/formatters/baseformatter.py +++ b/telegram_export/formatters/baseformatter.py @@ -46,6 +46,9 @@ 'id', 'name', 'mime_type', 'size', 'thumbnail_id', 'type', 'local_id', 'volume_id', 'secret', 'extra' )) +Forward = namedtuple('Forward', ( + 'id', 'original_date', 'from_id', 'channel_post', 'post_author' +)) class BaseFormatter: @@ -186,7 +189,7 @@ def format(self, target, file=None, *args, **kwargs): file = sys.stdout elif isinstance(file, (str, Path)): if os.path.isdir(file): - file = os.path.join(file, str(target)) + file = os.path.join(file, str(target)+ "." + self.name()) file = open(file, 'w') elif not isinstance(file, TextIOWrapper): # Is there a better way? raise TypeError( @@ -427,5 +430,30 @@ def get_media(self, mid): return None return Media(*row) + def get_forward(self, forward_id): + cur = self.dbconn.cursor() + cur.execute("SELECT ID, OriginalDate, FromID, ChannelPost, PostAuthor FROM Forward " + "WHERE ID = ?;", (forward_id,)) + row = cur.fetchone() + if not row: + return None + row = row[:1] + (datetime.datetime.fromtimestamp(row[1]),) + row[2:] + return Forward(*row) + + def get_human_readable_forwarded(self, forward): + if not forward: + return "Unknow forward" + if forward.from_id: + ent = self.get_user(forward.from_id) + if not ent: + return "Unknown user: %s" % forward.from_id + elif forward.channel_post: + ent = self.get_channel(forward.channel_post) + if not ent: + return "Unknown channel: %s" % forward.channel_post + else: + return "Unknown forward type" + return self.get_display_name(ent) + # if __name__ == '__main__': # main() diff --git a/telegram_export/formatters/htmlformatter.py b/telegram_export/formatters/htmlformatter.py index 9010ba9..b4956b6 100644 --- a/telegram_export/formatters/htmlformatter.py +++ b/telegram_export/formatters/htmlformatter.py @@ -4,6 +4,9 @@ """ from . import BaseFormatter +from .. import utils as export_utils +from .htmltemplates import * + class HtmlFormatter(BaseFormatter): """A Formatter class to generate HTML""" @@ -13,23 +16,55 @@ def name(): def output_header(self, file, context): """Output the header of the page. Context should be a namedtuple""" - # TODO HTML - print(self.get_display_name(context), file=file) + name = self.get_display_name(context) + + print(header.format(name, styles, name), file=file) - def generate_message_html(self, message): + def generate_message_html(self, message, context): """ Return HTML for a message, showing reply message, forward headers, view count, post author, and media (if applicable). """ - # TODO HTML from_name = self.get_display_name(message.from_id) or "(???)" - return "{}: {}".format(from_name, message.text) - def _format(self, context_id, file, *args, **kwargs): + if message.media_id: + media = self.get_media(message.media_id) + if media.type == 'photo': + + media_path = "%s-%s.%s%s" % (media.type, media.name, media.id, + export_utils.get_extension(media.mime_type)) + media_path = 'usermedia/%s-%s/%s' %(self.get_display_name(context), context.id, media_path) + body = photo_body_template.format(img_path=media_path) + else: + text = "Unsupported media type: %s. Message_id: %s, media_id: %s" % \ + (media.type, message.id, media.id) + body = normal_body_template.format(text=text) + else: + text = message.text + body = normal_body_template.format(text=text) + if message.reply_message_id: + body = reply_template.format(message_id=message.reply_message_id) + body + if message.forward_id: + forward = self.get_forward(message.forward_id) + body = forwaded_wrapper_template.format( + forward_from=self.get_human_readable_forwarded(forward), + body=body, + date=forward.original_date) + rendered = basic_message_template.format( + message_id=message.id, + from_name=from_name, + body=body, + full_date=message.date, + time=message.date.strftime("%H:%M")) + + return rendered + + def _format(self, context_id, file, *args, **kwargs,): """Format the given context as HTML and output to 'file'""" entity = self.get_entity(context_id) - + # file = sys.stdout self.output_header(file, entity) for message in self.get_messages_from_context(context_id, order='ASC'): - print(self.generate_message_html(message), file=file) + print(self.generate_message_html(message, entity), file=file) + print(footer, file=file) diff --git a/telegram_export/formatters/htmltemplates.py b/telegram_export/formatters/htmltemplates.py new file mode 100644 index 0000000..de374ce --- /dev/null +++ b/telegram_export/formatters/htmltemplates.py @@ -0,0 +1,150 @@ +column_width = 480 +styles = """ +body { + margin: 0; + font: 12px/18px 'Open Sans',"Lucida Grande","Lucida Sans Unicode",Arial,Helvetica,Verdana,sans-serif; +} +.page_body { + padding-top: 64px; + width: %spx; + margin: 0 auto; +} +.history { + padding: 16px 0; +} +.message { + margin: 0 -10px; + transition: background-color 2.0s ease; +} +.default { +padding: 10px +} +.default .from_name { + + color: #3892db; + font-weight: 700; + padding-bottom: 5px; + +} +.details { + + color: #70777b; + +} +.pull_right { + + float: right; + +} +.photo { +max-width: %spx; +} +.body { +margin-left: 40px; +} + +.page_header .content .text { + + padding: 24px 24px 22px 24px; + font-size: 22px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + +} +.bold { + + color: #212121; + font-weight: 700; + +} +.page_header .content { + + width: 480px; + margin: 0 auto; + border-radius: 0 !important; + +} +.page_header { + + position: fixed; + z-index: 10; + background-color: #ffffff; + width: 100%%; + border-bottom: 1px solid #e3e6e8; + +} +""" % (column_width, column_width - 20) + +header = """ + + + + + {} + + + + + + + + +
+
+""" + +footer = """ +
+
+ + +""" + +basic_message_template = """ +
+ +
+
+ {time} +
+
+ {from_name} +
+ {body} +
+
+""" + +normal_body_template = """ +
{text}
+""" +photo_body_template = """ +
+ +
+""" + +forwaded_wrapper_template = """ +
+
+ {forward_from} {date} +
+ {body} +
+""" +reply_template = """ +
+ In reply to this message +
+""" \ No newline at end of file