-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpublish.sh
More file actions
executable file
·164 lines (146 loc) · 5.4 KB
/
Copy pathpublish.sh
File metadata and controls
executable file
·164 lines (146 loc) · 5.4 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/bin/bash
# ==============================================================================
# Usage:
# export DEVTO_API_KEY="your_api_key_here"
# ./publish.sh <path_to_markdown_file>
#
# Description:
# Publishes/updates an article to Dev.to.
# - If 'organization_username: <name>' is in front matter, posts to that org.
# - Otherwise, posts as a personal article.
# - Extracts 'id' and 'published' from front matter.
# - Defaults 'published' to false.
# - Automatically writes back the Article ID upon creation.
# ==============================================================================
FILE_PATH=$1
# Function to display usage instructions
usage() {
echo "Usage: $0 <file_path>"
echo "Required Environment Variable: DEVTO_API_KEY"
exit 1
}
if [ -z "$FILE_PATH" ] || [ -z "$DEVTO_API_KEY" ]; then
usage
fi
if [ ! -f "$FILE_PATH" ]; then
echo "Error: File '$FILE_PATH' not found."
exit 1
fi
# 1. Extract Article ID
ARTICLE_ID=$(head -n 20 "$FILE_PATH" | grep -Ei "^id:[[:space:]]*[0-9]+" | head -n 1 | sed 's/[^0-9]//g')
# 2. Extract 'published' status
if [ "$USE_HUGO_DRAFT" = "true" ]; then
# Hugoモード: 'draft' を読み取って反転させる
EXTRACTED_DRAFT=$(head -n 20 "$FILE_PATH" | grep -Ei "^draft:[[:space:]]*(true|false)" | head -n 1 | awk '{print tolower($2)}' | xargs)
if [ "$EXTRACTED_DRAFT" = "true" ]; then
PUBLISHED_VALUE=false
elif [ "$EXTRACTED_DRAFT" = "false" ]; then
PUBLISHED_VALUE=true
else
PUBLISHED_VALUE=false
fi
else
# 従来モード: そのまま 'published' を読み取る
EXTRACTED_PUB=$(head -n 20 "$FILE_PATH" | grep -Ei "^published:[[:space:]]*(true|false)" | head -n 1 | awk '{print tolower($2)}' | xargs)
if [ "$EXTRACTED_PUB" = "true" ]; then
PUBLISHED_VALUE=true
else
PUBLISHED_VALUE=false
fi
fi
# 3. Extract Organization username (e.g., "organization_username: tinyalg")
ORG_USERNAME=$(head -n 20 "$FILE_PATH" | grep -Ei "^organization_username:[[:space:]]*[a-zA-Z0-9_-]+" | head -n 1 | sed 's/^[^:]*:[[:space:]]*//' | tr -d ' "\047')
# 4. Determine Organization ID
TARGET_ORG_ID=""
if [ -n "$ORG_USERNAME" ]; then
echo ">>> Resolving Organization ID for username: '$ORG_USERNAME'..."
ORG_API_RES=$(curl -s "https://dev.to/api/organizations/$ORG_USERNAME")
FETCHED_ORG_ID=$(echo "$ORG_API_RES" | grep -Eo '"id":[0-9]+' | head -n 1 | cut -d: -f2)
if [ -n "$FETCHED_ORG_ID" ]; then
TARGET_ORG_ID=$FETCHED_ORG_ID
echo " -> Found Organization ID: $TARGET_ORG_ID"
else
echo "Error: Could not find Organization '$ORG_USERNAME' on Dev.to."
exit 1
fi
else
echo ">>> No organization_username found. Will publish as a personal post."
fi
# 5. Read Markdown content
BODY_CONTENT=$(cat "$FILE_PATH")
# 6. Build JSON payload
# Omit organization_id completely if TARGET_ORG_ID is empty
JSON_PAYLOAD=$(jq -n \
--arg body "$BODY_CONTENT" \
--arg org "$TARGET_ORG_ID" \
--argjson pub "$PUBLISHED_VALUE" \
'if $org == "" then
{
"article": {
"body_markdown": $body,
"published": $pub
}
}
else
{
"article": {
"body_markdown": $body,
"published": $pub,
"organization_id": ($org | tonumber)
}
}
end')
# 7. Determine Method and URL
if [ -n "$ARTICLE_ID" ]; then
echo ">>> Mode: Update (Article ID: $ARTICLE_ID, Published: $PUBLISHED_VALUE)"
METHOD="PUT"
URL="https://dev.to/api/articles/$ARTICLE_ID"
else
echo ">>> Mode: New Publication (Published: $PUBLISHED_VALUE)"
METHOD="POST"
URL="https://dev.to/api/articles"
fi
# 8. Execute API Request
if [ "$DRY_RUN" = "true" ]; then
echo "=========================================="
echo "🚨 DRY RUN MODE ENABLED 🚨"
echo "Would execute: $METHOD $URL"
echo "Payload to send:"
echo "$JSON_PAYLOAD" | jq .
echo "=========================================="
# Simulate a successful Dev.to API response
if [ -z "$ARTICLE_ID" ]; then
MOCK_ID=$((RANDOM % 10000 + 9000000)) # 生成テスト用の適当なダミーID
RESPONSE="{\"id\":$MOCK_ID, \"url\":\"https://dev.to/mock/article-$MOCK_ID\"}"
else
RESPONSE="{\"id\":$ARTICLE_ID, \"url\":\"https://dev.to/mock/article-$ARTICLE_ID\"}"
fi
else
RESPONSE=$(curl -s -X "$METHOD" "$URL" \
-H "Content-Type: application/json" \
-H "api-key: $DEVTO_API_KEY" \
-d "$JSON_PAYLOAD")
fi
# 9. Parse and Update File
# Dev.to API may return unescaped control characters, which breaks jq.
# We use grep to safely extract the ID and URL directly as text.
NEW_ID=$(echo "$RESPONSE" | grep -Eo '"id":[0-9]+' | head -n 1 | cut -d: -f2)
ARTICLE_URL=$(echo "$RESPONSE" | grep -Eo '"url":"[^"]+"' | head -n 1 | cut -d'"' -f4)
if [ -n "$NEW_ID" ]; then
if [ -z "$ARTICLE_ID" ]; then
# For new posts, insert the ID safely into the second line
{
head -n 1 "$FILE_PATH"
echo "id: $NEW_ID"
tail -n +2 "$FILE_PATH"
} > "${FILE_PATH}.tmp" && mv "${FILE_PATH}.tmp" "$FILE_PATH"
echo "Success: Created with ID $NEW_ID"
else
echo "Success: Updated Article $ARTICLE_ID"
fi
echo "URL: $ARTICLE_URL"
else
echo "Error: API call failed or returned an unexpected format."
echo "$RESPONSE" | jq . || echo "$RESPONSE"
exit 1
fi