-
Notifications
You must be signed in to change notification settings - Fork 0
/
dev.py
93 lines (78 loc) · 3.35 KB
/
dev.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from syndicate.utils import action_log_group, action_log, action_error, fronted, silo_id_for
import requests
import pprint
SILO_NAME = 'DEV'
@action_log_group(SILO_NAME)
def syndicate(posts, api_key):
"""
Syndicates the given posts to https://dev.to, updating the ones that
already exist there and creating articles for the ones that don't.
By default, articles are created in a "draft"/unpublished state, but this
can be overridden by individual posts by specifying `published: true` in
their frontmatter, if you prefer a "just do it" approach.
This uses the DEV API, which is currently in beta: https://docs.dev.to/api
The required API key can be generated for your account by following the steps
outlined here: https://docs.dev.to/api/#section/Authentication
"""
action_log(f"Hello? Yes, this is {SILO_NAME}.")
results = {
'added': {post.path:_create(post, api_key) for post in posts if not silo_id_for(post, SILO_NAME)},
'modified': {post.path:_update(post, api_key) for post in posts if silo_id_for(post, SILO_NAME)}
}
action_log("The results are in:")
action_log(pprint.pformat(results))
return results
### privates ###
def _create(post, api_key=None):
"""
Creates a new article for the given post on DEV.to and returns the silo ID
and URL of the newly created article.
This tries to create an **unpublished** draft. However, the 'published'
status can be overridden in the frontmatter of the post itself for a
"just do it" approach.
@see https://docs.dev.to/api/#operation/createArticle
"""
if not api_key:
raise ValueError("missing API key")
if not post:
raise ValueError("missing post")
if not fronted(post).get('title'):
raise ValueError("article is missing a title")
payload = {
'article': {
# NOTE This can be overridden by explicitly setting 'published' in
# the frontmatter.
'published': False,
'body_markdown': post.decoded_content.decode('utf-8')
}
}
endpoint = "https://dev.to/api/articles"
headers = {'api-key': api_key}
response = requests.post(endpoint, headers=headers, json=payload)
if response.status_code != requests.codes.created:
action_error(f"Failed to create draft for '{post.name}': {response.json()}")
return None
else:
results = response.json()
return (results['id'], results['url'])
def _update(post, api_key=None):
"""
Updates an article corresponding to the given post on DEV.to and returns the
silo ID and URL of the updated arcticle.
If a corresponding article does not exist, this will fail.
@see https://docs.dev.to/api/#operation/updateArticle
"""
if not api_key:
raise ValueError("missing API key")
if not post:
raise ValueError("missing post")
endpoint = f'https://dev.to/api/articles/{silo_id_for(post, SILO_NAME)}'
headers = {'api-key': api_key}
payload = {'article': { 'body_markdown': post.decoded_content.decode('utf-8') } }
response = requests.put(endpoint, headers=headers, json=payload)
if response.status_code != requests.codes.ok:
action_error(f"Failed to update post '{post.name}': {response.json()}")
return None
else:
results = response.json()
return (results['id'], results['url'])