[개발이야기#035] 내가 해보고 싶은 것 - 자동 보팅 프로그램 하루에 한번 보팅하는 프로그램[postingcuration]
안녕하세요 가야태자 @talkit 입니다.
오늘은 드디어 앞에서 작성한 프로그램을 이용해서 보팅을 시작 합니다.
user 테이블에 들어 있는 정해진 사용자와 postings 테이블에 들어 있는 최근글을 기준으로 보팅을 진행 합니다.
보팅 파워는 75%로 합니다.
관련글
[개발이야기#028] 내가 해보고 싶은 것 - 자동 보팅 프로그램 SQLite vs DuckDB [postingcuration]
[개발이야기#029] 내가 해보고 싶은 것 - 자동 보팅 프로그램 사용자 및 포스트 테이블 생성하기 [postingcuration]
[개발이야기#031] 내가 해보고 싶은 것 - 자동 보팅 프로그램 사용자 등록 프로그램 작성하기 [postingcuration]
[개발이야기#032] 내가 해보고 싶은 것 - 자동 보팅 프로그램 사용자 게시글 수집기 작성하기 [postingcuration]
[개발이야기#034] 내가 해보고 싶은 것 - 포스팅 큐레이션 글을 자동으로 정리해보자 [postingcuration]
[개발이야기#034] 내가 해보고 싶은 것 - 포스팅 큐레이션 글 목록을 자동 포스팅 하기 [postingcuration]
코드 컨셉트
이글을 실제로 10월 12일 다시 작성했습니다. 발행일은 언제가 될지 아마도 13일일 것 같습니다.
^^
원래는 75% 파워로 보팅을 해드리려고 했는데 보팅 파워에 한계가 있기도 하고,
오늘 파워업을 진행 했습니다.
그래서 스팀파워가 2000이 되었구요.
그랬더니
이게 가능하네요 ^^
그래서 보팅 파워는 50%로 결정을 했습니다.
우선은 지금 현재 #postingcuration 참여자분들께 보팅해드리고 있습니다.
소스 코드
from steem import Steem
import duckdb
from datetime import datetime, timedelta
# Steemit 계정 정보
STEEM_USERNAME = 'your_steemit_id'
STEEM_POSTING_KEY = 'your_posting_key' # 여기에 실제 posting key를 넣어주세요
# Steemit 객체 생성
steem = Steem(keys=[STEEM_POSTING_KEY])
# DuckDB 연결 설정
conn = duckdb.connect('steemit_auto_posting.db')
# 로그 함수
def log(message):
print(f"{datetime.now()} - {message}")
# 특정 사용자에 대한 최근 게시물 조회 함수
def fetch_recent_posts_for_voting(username, days=3):
try:
# 3일 이내의 게시물 조회 (글의 작성일 기준) 및 voting_status가 false인 경우만
cutoff_date = datetime.utcnow() - timedelta(days=days)
query = """
SELECT post_id, title, posting_date
FROM postings
WHERE user_id = ? AND posting_date >= ? AND voting_status = false
ORDER BY posting_date DESC
"""
df = conn.execute(query, (username, cutoff_date)).fetchdf()
return df
except Exception as e:
log(f"An error occurred while fetching posts for {username}: {e}")
return None
# 이미 보팅했는지 확인하는 함수
def has_voted(author, permlink, voter):
try:
votes = steem.get_active_votes(author, permlink)
# 해당 보팅 리스트에 계정이 있는지 확인
return any(vote['voter'] == voter for vote in votes)
except Exception as e:
log(f"An error occurred while checking votes on post {author}/{permlink}: {e}")
return False
# 보팅 로그 테이블에 보팅 기록 삽입
def log_voting_to_db(post_url, user_id, voting_status):
try:
current_time = datetime.utcnow()
query = """
INSERT INTO voting_logs (url, user_id, voting_status, voting_date)
VALUES (?, ?, ?, ?)
"""
conn.execute(query, (post_url, user_id, voting_status, current_time))
log(f"Inserted voting record into voting_logs for post: {post_url}")
except Exception as e:
log(f"An error occurred while logging voting info to database: {e}")
# 보팅 함수
def vote_post(post_url, voter, user_id, weight=50):
try:
# URL에서 author와 permlink 추출
parts = post_url.split("/")
author = parts[-2].replace('@', '')
permlink = parts[-1]
# 이미 보팅했는지 확인
if has_voted(author, permlink, voter):
log(f"Already voted on post: {post_url} by {voter}")
# 이미 보팅된 경우 voting_status를 true로, modified_at을 현재 시간으로 업데이트
update_voting_status(post_url, True)
# 보팅 기록 삽입
log_voting_to_db(post_url, user_id, True)
return
# Steemit에 보팅
identifier = ('@'+author+'/'+permlink)
steem.commit.vote(identifier, float(weight), voter)
log(f"Successfully voted on post: {post_url} by {voter}")
# 보팅 완료 후 voting_status를 true로, modified_at을 현재 시간으로 업데이트
update_voting_status(post_url, True)
# 보팅 기록 삽입
log_voting_to_db(post_url, user_id, True)
except Exception as e:
log(f"An error occurred while voting on post {post_url}: {e}")
# 오류 발생 시에도 voting_status를 true로 업데이트하여 다시 시도되지 않도록 함
update_voting_status(post_url, True)
# voting_status 및 modified_at 업데이트 함수
def update_voting_status(post_url, status):
try:
# 현재 시간을 modified_at에 설정
current_time = datetime.utcnow()
# voting_status 업데이트
query = """
UPDATE postings
SET voting_status = ?, modified_at = ?
WHERE post_id = ?
"""
conn.execute(query, (status, current_time, post_url))
log(f"Updated voting status for post: {post_url}")
except Exception as e:
log(f"An error occurred while updating voting status for post {post_url}: {e}")
# 사용자 목록 가져오기 함수 (최근 24시간 이내 보팅하지 않은 사용자만)
def get_users():
try:
log("Fetching active users from database")
# 24시간 이전의 시각을 cutoff로 설정
cutoff_date = datetime.utcnow() - timedelta(hours=24)
# 최근 24시간 내에 voting_logs에 없는 사용자 가져오기
query = """
SELECT DISTINCT user_id FROM users
WHERE is_active = 'Y'
AND user_id NOT IN (
SELECT DISTINCT user_id FROM voting_logs WHERE voting_date >= ?
) order by user_id ASC limit 1
"""
df_users = conn.execute(query, (cutoff_date,)).fetchdf()
return df_users['user_id'].tolist()
except Exception as e:
log(f"An error occurred while fetching users: {e}")
return []
def main():
# 활성화된 사용자 목록 가져오기
users = get_users()
for user in users:
log(f"Checking posts for user {user}...")
# 3일 이내의 게시물 가져오기
posts_df = fetch_recent_posts_for_voting(user, days=3)
if posts_df is not None and not posts_df.empty:
# 최신 글의 URL 추출
post_url = posts_df.iloc[0]['post_id']
log(f"Found post to vote on for user {user}: {post_url}")
# 보팅 실행
vote_post(post_url, voter=STEEM_USERNAME, user_id=user, weight=50)
else:
# 현재 날짜 및 시간 가져오기
current_time = datetime.now()
# 원하는 형식으로 변환 (YYYYMMDDHH24MMII)
formatted_time = current_time.strftime('%Y%m%d%H%M%S')
log_voting_to_db("novoteurl_" + formatted_time, user, True)
log(f"No recent posts to vote on for user {user}")
if __name__ == "__main__":
main()
코드 설명
이 스크립트는 Steemit 플랫폼에서 특정 사용자의 최신 게시물에 자동으로 보팅을 수행하는 자동화된 과정을 제공합니다. 사용자는 DuckDB 데이터베이스를 통해 관리되며, 스크립트는 다음과 같은 주요 기능을 수행합니다:
- 사용자 인증 및 설정: 사용자의 스팀 계정과 개인 키를 이용하여 Steem 라이브러리를 초기화합니다.
- DuckDB 연결: 로컬 DuckDB 데이터베이스에 연결하여 사용자 데이터 및 게시물 정보를 저장 및 조회합니다.
- 최근 게시물 조회: 지정된 사용자의 최근 게시물을 조회합니다. 이때 조회 기간은 기본적으로 3일로 설정되어 있으며, 아직 보팅이 이루어지지 않은 게시물을 대상으로 합니다.
- 보팅 확인 및 실행: 조회된 게시물에 대해 현재 사용자가 이미 보팅을 했는지 확인하고, 보팅을 하지 않았다면 보팅을 수행합니다.
- 보팅 결과 로깅: 보팅의 결과와 과정을 데이터베이스에 로깅하여 추후 조회가 가능하도록 합니다.
이 과정을 통해, 스크립트는 정기적으로 특정 사용자의 게시물에 대한 지원을 자동화하고, 이에 대한 기록을 유지합니다. 스크립트는 주기적으로 실행되어 사용자의 활동을 지원하며, 이를 통해 사용자 간의 상호 작용 및 지원을 증진시키는 데 목적이 있습니다.
스크립트의 각 부분은 사용자와 관련된 데이터를 안전하게 처리하며, 모든 트랜잭션과 사용자 상호작용은 Steem 블록체인과 DuckDB 데이터베이스를 통해 관리됩니다. 이를 통해 스크립트는 효율적이고 자동화된 방식으로 Steemit 커뮤니티 내에서 활동을 지원할 수 있습니다.
실행하면 하나의 사용자만 보팅 하는 이유
query = """
SELECT DISTINCT user_id FROM users
WHERE is_active = 'Y'
AND user_id NOT IN (
SELECT DISTINCT user_id FROM voting_logs WHERE voting_date >= ?
) order by user_id ASC limit 1
"""
여기 코드를 이 프로그램은 코드를 실행하면 1명의 사용자에게만 보팅을 진행 합니다.
이유는 보팅 파워 때문입니다. ^^
제가 알고 있는 지식으로 100%보팅을 하면 2%의 보팅 파워가 깍인다고 알고 있습니다.
이 2%가 98%일때 다시 100으로 복구되는 시간은 2시간입니다. ^^
그래서 저는 1시간에 1번씩 보팅을 진행하고 있습니다.
75%파워로 진행하고 있었고, 1.5%정도를 갈아 먹고 1정도의 보팅 파워가 찹니다. ^^
그래서 조금 유지되는 형태로 했고,
현재 데이터 베이스에는 21분의 사용자가 들어 있습니다.
이 사용자들에게 보팅을 하면 24시간중에 3시간 정도가 남는데 이것 때문에 60~75% 사이를 유지하고 있는 것 같습니다.
보팅 파워를 50%로 조정 했고, 조정된 보팅파워와 어느정도 되는지를 보고 보팅 시간을 30분 정도로 줄여 보려고 생각하고 있습니다.
이건 실제로 또 해보고 글로 남겨 드리겠습니다.
저도 50%로 0.01을 찍어 드리는 것은 처음이라 기대하고 있습니다.
이렇게 했을때 20분보다 더 많은 사용자들을 자동으로 보팅할 수 있을 것으로 기대 됩니다.
실행 방법
저는 이 프로그램으로 매일 매일 참가자 분들께 보팅을 해드리고 있습니다.
auto_voting_user_account2.py
코드를 복사하셔서 위 파일명으로 저장하십시오.
conda activate steemit
저를 계속 따라하셨다면 steemit 가상환경을 켜시구요.
혹시나 처음이시라면 앞에 글을 참조하시거나, 다음글에 실행 방법을 정리해보겠습니다.
python auto_voting_user_account2.py
위와 같이 실행하시면 됩니다.
결론
지금까지 열심히 자동 보팅 프로그램을 작성했습니다.
저는 자동으로 보팅을 하고 있어서 글을 쓰고 있는 지금도 ^^ 아래와 같이 보팅이 잘 되고 있습니다.
2024-10-12 21:29:52.450495 - Fetching active users from database
2024-10-12 21:29:52.832574 - Checking posts for user syskwl...
2024-10-12 21:29:52.835504 - Found post to vote on for user syskwl: https://steemit.com/kr/@syskwl/5ufbqd-1
2024-10-12 21:29:54.388941 - Successfully voted on post: https://steemit.com/kr/@syskwl/5ufbqd-1 by talkit
2024-10-12 21:29:54.390901 - Updated voting status for post: https://steemit.com/kr/@syskwl/5ufbqd-1
2024-10-12 21:29:54.392852 - Inserted voting record into voting_logs for post: https://steemit.com/kr/@syskwl/5ufbqd-1
Finished running auto_voting_user_account2.py
위 프로그램을 가지고 1시간마다 한번식 수동으로 실행하시면 ^^ 보팅이 됩니다.
그런데 사람이 하면 시간 맞추기도 힘들고 해서
다음 포스팅에 steem_schedule.py를 공개하겠습니다.
저는 저걸 이용해서 진행하고 있습니다.
리눅스 시라면 리눅스의 crontab
을 사용하셔도 됩니다.
하지만, 제 마음대로 조정할 수 있는 스케쥴러가 요즘 친해지고자하는 python
에서 사용해보고 있습니다.
감사합니다.
Posted through the ECblog app (https://blog.etain.club)
[광고] STEEM 개발자 커뮤니티에 참여 하시면, 다양한 혜택을 받을 수 있습니다.
와~ 멋지세요!
저도 이번 큐레이팅 대회에 참여하고 계신분들께 조금이라도 보팅을 해드리고 싶은데~
어서 따라해봐야겠습니다!
고맙습니다~ ^^
^^ 저는 자고 있어도
보팅이 잘 되고 있습니다. ^^
오늘 새벽에 스케쥴러가 요거트님까 보팅을 잘 했네요 ^^
모르지만 멋있습니다!
감사합니다.
@dozam 님글에도 하루에 네번째로 ^^ 보팅을 자동으로 해드리고 있네요 ^^
새로운 한주도 즐거운 한주 되시기를