Skip to content
This repository has been archived by the owner on Oct 23, 2019. It is now read-only.

add html formating #92

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion telegram_export/formatters/baseformatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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:]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See how the other functions do this: they construct the namedtuple first, then use something like _replace(original_date=datetime.datetime.fromtimestamp(original_date)

return Forward(*row)

def get_human_readable_forwarded(self, forward):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in my comment, I think this should be moved to a higher level (i.e. htmlformatter)

if not forward:
return "Unknow forward"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo here.

if forward.from_id:
ent = self.get_user(forward.from_id)
if not ent:
return "Unknown user: %s" % forward.from_id
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change these % formats to use "{}".format() style formatting

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()
51 changes: 43 additions & 8 deletions telegram_export/formatters/htmlformatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"""
from . import BaseFormatter

import utils as export_utils
mr-tron marked this conversation as resolved.
Show resolved Hide resolved
from .htmltemplates import *
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import * should be avoided if possible. I understand that you want to import a lot of names for templates, but it's totally fine to have a long import line like
from .htmltemplates import column_width, styles, header, basic_message_template, normal_body_template

Alternatively, use a namespaced import so you can do things like templates.styles, templates.basic_message, templates.normal_body

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@expectocode you should try the new beta feature from GitHub

```suggestion
from .htmltemplates import column_width, styles, header, basic_message_template, normal_body_template
```



class HtmlFormatter(BaseFormatter):
"""A Formatter class to generate HTML"""
Expand All @@ -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,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

% formatting, again.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The media path is user-configurable, so ideally this would use the format string specified by the user. I understand that is a bit more work, and perhaps should be in the BaseFormatter. It really should happen before rolling out to users, though.

export_utils.get_extension(media.mime_type))
media_path = 'usermedia/%s-%s/%s' %(self.get_display_name(context), context.id, media_path)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name shadowing on media_path is confusing.

body = photo_body_template.format(img_path=media_path)
else:
text = "Unsupported media type: %s. Message_id: %s, media_id: %s" % \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

% formatting

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With inconsistent spacing. But yes, use .format().

(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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it should have been deleted

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)
150 changes: 150 additions & 0 deletions telegram_export/formatters/htmltemplates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
column_width = 480
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a comment about what this controls?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not totally necessary, just a thought. Of course, comments aren't the best solution as they can become outdated.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments aren't the best solution as they can become outdated.

That's a poor argument. Maybe telegram-export could support --formatter-params column_width=480, or something like that. Having a standard way to define which parameters are valid could also help with error diagnostics, help or just listing options.

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)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

% formatting


header = """
<html lang="en">
<head>
<meta charset="utf-8">

<title>{}</title>
<meta name="description" content="The HTML5 Herald">
<meta name="author" content="SitePoint">
<style type="text/css">{}</style>

</head>

<body>
<div class="page_header">

<div class="content">

<div class="text bold">
{}
</div>

</div>

</div>
<div class="page_body chat_page">
<div class='history'>
"""

footer = """
</div>
</div>
</body>
</html>
"""

basic_message_template = """
<div class="message default clearfix" id="message{message_id}" >
<a name="message{message_id}"></a>
<div class="body">
<div class="pull_right date details" title="{full_date}">
{time}
</div>
<div class="from_name">
{from_name}
</div>
{body}
</div>
</div>
"""

normal_body_template = """
<div class="text">{text}</div>
"""
photo_body_template = """
<div class="img_body">
<a href="{img_path}"> <img class='photo' src="{img_path}"></img></a>
</div>
"""

forwaded_wrapper_template = """
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
forwaded_wrapper_template = """
forwarded_wrapper_template = """

<div class="body">
<div class="from_name">
{forward_from} <span class='details'>{date}</span>
</div>
{body}
</div>
"""
reply_template = """
<div class="reply_to details">
In reply to <a href="#message{message_id}">this message</a>
</div>
"""