initial commit - email2post.py
This commit is contained in:
commit
6babc1b53b
4 changed files with 189 additions and 0 deletions
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 Morgan McMillian
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# blarp - a collection of my social posting bits
|
||||
|
||||
## email2post.py
|
||||
|
||||
Parse email from STDIN and create a post on one or more social network.
|
||||
Currently supports mastodon and pnut.io.
|
||||
|
159
email2post.py
Executable file
159
email2post.py
Executable file
|
@ -0,0 +1,159 @@
|
|||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import os
|
||||
import email
|
||||
import email.header
|
||||
import textwrap
|
||||
import logging
|
||||
import argparse
|
||||
import configparser
|
||||
|
||||
import pnutpy
|
||||
|
||||
from mastodon import Mastodon
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
def parse(data, pnut, mstdn):
|
||||
body = ""
|
||||
attachments = []
|
||||
|
||||
for part in data.walk():
|
||||
disposition = part.get_content_disposition()
|
||||
contentType = part.get_content_type()
|
||||
|
||||
if contentType == "multipart/mixed":
|
||||
continue
|
||||
|
||||
if disposition == "inline":
|
||||
body = part.get_payload(decode=True).decode("utf-8")
|
||||
|
||||
elif disposition == "attachment":
|
||||
attachment = part.get_payload(decode=True)
|
||||
filename = part.get_filename()
|
||||
attachments.append({
|
||||
'type': contentType,
|
||||
'filename': filename,
|
||||
'file': attachment
|
||||
})
|
||||
|
||||
else:
|
||||
logger.debug("unknown disposition")
|
||||
logger.debug(disposition)
|
||||
|
||||
if pnut:
|
||||
post_pnut(data['Subject'], body, attachments)
|
||||
|
||||
if mstdn:
|
||||
post_mastodon(data['Subject'], body, attachments)
|
||||
|
||||
def post_pnut(title, text, attachments):
|
||||
post = {'text': text, 'raw': []}
|
||||
|
||||
mtext = textwrap.wrap(text, 254)
|
||||
if len(mtext) > 1:
|
||||
longpost = {
|
||||
'title': title,
|
||||
'body': text,
|
||||
'tstamp': time.time() * 1000
|
||||
}
|
||||
pretext = textwrap.wrap(text, 100)
|
||||
post['text'] = pretext[0]
|
||||
post['text'] += "... - https://longpo.st/p/{object_id} - #longpost"
|
||||
post['raw'].append({
|
||||
'type': "nl.chimpnut.blog.post",
|
||||
'value': longpost
|
||||
})
|
||||
|
||||
for attachment in attachments:
|
||||
try:
|
||||
file_, meta = pnutpy.api.create_file(
|
||||
files={'content': attachment['file']},
|
||||
data={
|
||||
'name': attachment['filename'],
|
||||
'type': 'dev.thrrgilag.blarp',
|
||||
'is_public': 'true'
|
||||
}
|
||||
)
|
||||
value = {
|
||||
'+io.pnut.core.file': {
|
||||
'file_id': file_.id,
|
||||
'file_token': file_.file_token,
|
||||
'format': 'oembed'
|
||||
}
|
||||
}
|
||||
post['raw'].append({
|
||||
'type': "io.pnut.core.oembed",
|
||||
'value': value
|
||||
})
|
||||
|
||||
except Exception:
|
||||
logger.error("problem handling an attachment")
|
||||
logger.exception("pnut attachment")
|
||||
return
|
||||
|
||||
try:
|
||||
response, meta = pnutpy.api.create_post(data=post)
|
||||
logger.debug(response)
|
||||
|
||||
except Exception:
|
||||
logger.error("problem posting to pnut")
|
||||
logger.exception("create_post")
|
||||
|
||||
def post_mastodon(title, text, attachments):
|
||||
media_ids = []
|
||||
|
||||
for attachment in attachments:
|
||||
file_ = mastodon.media_post(attachment['file'], attachment['type'])
|
||||
media_ids.append(file_['id'])
|
||||
|
||||
response = mastodon.status_post(text, media_ids=media_ids)
|
||||
logger.debug(response)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if "XDG_CONFIG_HOME" in os.environ:
|
||||
config_home = os.path.expanduser(os.environ["XDG_CONFIG_HOME"])
|
||||
config_file = os.path.join(config_home, "email2post.conf")
|
||||
else:
|
||||
config_home = os.path.expanduser("~")
|
||||
config_file = os.path.join(config_home, ".email2post.conf")
|
||||
|
||||
a_parser = argparse.ArgumentParser()
|
||||
a_parser.add_argument(
|
||||
'-d', '--debug', action='store_true', dest='debug',
|
||||
help="debug"
|
||||
)
|
||||
a_parser.add_argument(
|
||||
'-c', '--config', dest='config_file',
|
||||
)
|
||||
a_parser.add_argument(
|
||||
'-p', '--pnut', action='store_true', dest='pnut',
|
||||
help="post to pnut.io"
|
||||
)
|
||||
a_parser.add_argument(
|
||||
'-m', '--mastodon', action='store_true', dest='mstdn',
|
||||
help="post to mastodon"
|
||||
)
|
||||
args = a_parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
if args.config_file:
|
||||
config_file = args.config_file
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_file)
|
||||
|
||||
pnutpy.api.add_authorization_token(config['pnut']['token'])
|
||||
|
||||
mastodon = Mastodon(
|
||||
client_id=config['mastodon']['client_id'],
|
||||
client_secret=config['mastodon']['client_secret'],
|
||||
access_token=config['mastodon']['access_token'],
|
||||
api_base_url=config['mastodon']['url']
|
||||
)
|
||||
|
||||
data = email.message_from_file(sys.stdin)
|
||||
parse(data, args.pnut, args.mstdn)
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
pnutpy
|
||||
Mastodon.py
|
Loading…
Reference in a new issue