Compare commits

...

11 Commits

Author SHA1 Message Date
5124b13e59 Force deploy
All checks were successful
Apps/everybody-mov/pipeline/head This commit looks good
2022-09-04 01:31:08 -04:00
9d3b41f338 Performing better masking on credentials; renaming env variables; cleaning up after Docker agents.
All checks were successful
Apps/everybody-mov/pipeline/head This commit looks good
2022-09-03 23:44:14 -04:00
5e4a63af9c Only publish on main
All checks were successful
Apps/everybody-mov/pipeline/head This commit looks good
2022-09-02 00:39:07 -04:00
cbc3cc26ed Merge branch 'main' of https://ailuridae.io/git/amber/everybody-mov
All checks were successful
Apps/everybody-mov/pipeline/head This commit looks good
Merging main
2022-09-02 00:37:06 -04:00
a066142307 Adding Jenkinsfile for checking, building, and publishing 2022-09-02 00:35:32 -04:00
6a90b91f3a Undoing one grammatical edit in everybody.txt 2022-08-30 18:59:50 +00:00
693749f1ea Grammatical edits to everybody.txt 2022-08-30 18:53:33 +00:00
0a996ad14c Specifying how to build in README.md, in case I forget. 2022-08-28 22:51:40 -04:00
63b3efaa9b Styling changes and fixing some dumb dumb code. Also, some new dependencies for development. 2022-08-28 22:42:43 -04:00
8158c727bc Merge branch 'main' of https://ailuridae.io/git/amber/everybody-mov 2022-08-26 02:52:29 -04:00
96d31ba8d3 Fixing environment variable glitch 2022-08-26 02:52:09 -04:00
9 changed files with 263 additions and 42 deletions

5
.gitignore vendored
View File

@@ -140,10 +140,6 @@ cython_debug/
# ---> VisualStudioCode # ---> VisualStudioCode
.vscode/* .vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace *.code-workspace
# Local History for Visual Studio Code # Local History for Visual Studio Code
@@ -234,6 +230,7 @@ fabric.properties
# Icon must end with two \r # Icon must end with two \r
Icon Icon
# Thumbnails # Thumbnails
._* ._*

8
.groovylintrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "recommended",
"rules": {
"NestedBlockDepth": {
"enabled": false
}
}
}

View File

@@ -1,9 +1,9 @@
FROM python:3.10-alpine FROM python:3.10-alpine
WORKDIR /app WORKDIR /app/
ENV PYTHONIOENCODING=utf-8 ENV PYTHONIOENCODING=utf-8
COPY Pipfile Pipfile.lock everybody.txt tweetbot.py /app COPY Pipfile Pipfile.lock everybody.txt tweetbot.py /app/
# Install pipenv and compilation dependencies # Install pipenv and compilation dependencies
RUN pip install pipenv && pipenv install --deploy --ignore-pipfile RUN pip install pipenv && pipenv install --deploy --ignore-pipfile

95
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,95 @@
pipeline {
agent none
environment {
HOME = "${env.WORKSPACE}"
PYTHON_IMAGE = 'python:3.10-slim-bullseye'
CREDENTIALS_ID = 'digital-ocean-ailuridae-registry'
REGISTRY = 'https://registry.digitalocean.com'
IMAGE_NAME = 'registry.digitalocean.com/ailuridae-registry/ailuridae.io/everybodymov'
IMAGE_BUILD = ''
APP_ID = credentials('digital-ocean-app-id')
}
stages {
stage('Check') {
agent {
docker {
image env.PYTHON_IMAGE
args '--rm'
}
}
steps {
sh 'python -m pip install --no-cache-dir --upgrade --user pip'
sh 'python -m pip install --no-cache-dir --user pipenv'
sh 'python -m pipenv install --dev --deploy'
sh 'python -m pipenv check --clear'
sh 'python -m pipenv run bandit *.py'
}
}
stage('Build') {
agent {
label 'main'
}
steps {
script {
IMAGE_BUILD = docker.build("${IMAGE_NAME}")
}
}
}
stage('Publish') {
agent {
label 'main'
}
when {
branch 'main'
}
steps {
script {
// withCredentials is annoyingly required to mask token occurrences.
withCredentials([usernamePassword(
credentialsId: env.CREDENTIALS_ID,
usernameVariable: 'API_TOKEN_USER',
passwordVariable: 'API_TOKEN_PASS'
)]) {
docker.withRegistry(env.REGISTRY, env.CREDENTIALS_ID) {
IMAGE_BUILD.push("${BUILD_NUMBER}")
IMAGE_BUILD.push('latest')
}
}
}
}
}
stage('Deploy') {
agent {
label 'main'
}
when {
branch 'main'
}
steps {
script {
withCredentials([usernamePassword(
credentialsId: env.CREDENTIALS_ID,
usernameVariable: 'API_TOKEN_USER',
passwordVariable: 'API_TOKEN_PASS'
)]) {
sh '''
curl -H "Authorization: Bearer $API_TOKEN_PASS" -H "Content-Type: application/json" \
-X POST "https://api.digitalocean.com/v2/apps/$APP_ID/deployments" \
-d "{ \\"force_build\\" : true }"
'''
}
}
}
}
}
post {
always {
node('main') {
cleanWs()
}
}
}
}

View File

@@ -7,7 +7,8 @@ name = "pypi"
tweepy = "==4.10.1" tweepy = "==4.10.1"
[dev-packages] [dev-packages]
autopep8 = "==1.7.0" autopep8 = "*"
bandit = "*"
[requires] [requires]
python_version = "3.10" python_version = "3.10"

95
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "a94545d640dcc28fce0a26b5d40dfaebf886910d87df38ab7bbe4ab7ec69f066" "sha256": "e7a1785570cb6182573b0e15cae2ad2c86adb2c280e88ceaa9126c232b720c9c"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@@ -21,7 +21,7 @@
"sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d", "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d",
"sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"
], ],
"markers": "python_version >= '3.6'", "markers": "python_full_version >= '3.6.0'",
"version": "==2022.6.15" "version": "==2022.6.15"
}, },
"charset-normalizer": { "charset-normalizer": {
@@ -29,7 +29,7 @@
"sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845",
"sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"
], ],
"markers": "python_version >= '3.6'", "markers": "python_full_version >= '3.6.0'",
"version": "==2.1.1" "version": "==2.1.1"
}, },
"idna": { "idna": {
@@ -45,7 +45,7 @@
"sha256:23a8208d75b902797ea29fd31fa80a15ed9dc2c6c16fe73f5d346f83f6fa27a2", "sha256:23a8208d75b902797ea29fd31fa80a15ed9dc2c6c16fe73f5d346f83f6fa27a2",
"sha256:6db33440354787f9b7f3a6dbd4febf5d0f93758354060e802f6c06cb493022fe" "sha256:6db33440354787f9b7f3a6dbd4febf5d0f93758354060e802f6c06cb493022fe"
], ],
"markers": "python_version >= '3.6'", "markers": "python_full_version >= '3.6.0'",
"version": "==3.2.0" "version": "==3.2.0"
}, },
"requests": { "requests": {
@@ -90,6 +90,38 @@
"index": "pypi", "index": "pypi",
"version": "==1.7.0" "version": "==1.7.0"
}, },
"bandit": {
"hashes": [
"sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2",
"sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"
],
"index": "pypi",
"version": "==1.7.4"
},
"gitdb": {
"hashes": [
"sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd",
"sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"
],
"markers": "python_version >= '3.6'",
"version": "==4.0.9"
},
"gitpython": {
"hashes": [
"sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704",
"sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"
],
"markers": "python_version >= '3.7'",
"version": "==3.1.27"
},
"pbr": {
"hashes": [
"sha256:cfcc4ff8e698256fc17ea3ff796478b050852585aa5bae79ecd05b2ab7b39b9a",
"sha256:da3e18aac0a3c003e9eea1a81bd23e5a3a75d745670dcf736317b7d966887fdf"
],
"markers": "python_version >= '2.6'",
"version": "==5.10.0"
},
"pycodestyle": { "pycodestyle": {
"hashes": [ "hashes": [
"sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785",
@@ -98,6 +130,61 @@
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==2.9.1" "version": "==2.9.1"
}, },
"pyyaml": {
"hashes": [
"sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293",
"sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b",
"sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57",
"sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b",
"sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4",
"sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07",
"sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba",
"sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9",
"sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287",
"sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513",
"sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0",
"sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0",
"sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92",
"sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f",
"sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2",
"sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc",
"sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c",
"sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86",
"sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4",
"sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c",
"sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34",
"sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b",
"sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c",
"sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb",
"sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737",
"sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3",
"sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d",
"sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53",
"sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78",
"sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803",
"sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a",
"sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174",
"sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"
],
"markers": "python_version >= '3.6'",
"version": "==6.0"
},
"smmap": {
"hashes": [
"sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94",
"sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"
],
"markers": "python_version >= '3.6'",
"version": "==5.0.0"
},
"stevedore": {
"hashes": [
"sha256:87e4d27fe96d0d7e4fc24f0cbe3463baae4ec51e81d95fbe60d2474636e0c7d8",
"sha256:f82cc99a1ff552310d19c379827c2c64dd9f85a38bcd5559db2470161867b786"
],
"markers": "python_version >= '3.8'",
"version": "==4.0.0"
},
"toml": { "toml": {
"hashes": [ "hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",

View File

@@ -1,2 +1,12 @@
# everybody-mov # everybody-mov
In my dreams there is an intimacy I have never known. In my dreams there is an intimacy I have never known.
## Building image
```
docker buildx build --platform linux/amd64 -t ailuridae.io/everybodymov .
```
## Running container
```
docker run -e CONSUMER_KEY=mykey -e CONSUMER_SECRET=mysecret -e ACCESS_TOKEN=mytoken -e ACCESS_TOKEN_SECRET=mytokensecret ailuridae.io/everybodymov:latest
```

View File

@@ -8,7 +8,7 @@ Feverish sensations fill my blood from matters of a violent and unfulfilled desi
You are made of beets. I think this is wonderful. You are made of beets. I think this is wonderful. You are made of beets. I think this is wonderful. You are made of beets. I think this is wonderful.
I wished for her to remove them one by one with her mouth. I wished for her to remove them one by one with her mouth.
It would cause a hemorrhage, of this I am certain. It would cause a hemorrhage, of this I am certain.
When she is not around I do not exist at all. When she is not around, I do not exist at all.
A pathological disorder, let's be honest. A pathological disorder, let's be honest.
In my dreams there is an intimacy I have never known. In my dreams there is an intimacy I have never known.
These newfound discoveries are causing me to spray strange oily liquids. These newfound discoveries are causing me to spray strange oily liquids.
@@ -17,7 +17,7 @@ You are too needy, dripping with need. You should probably kill yourself before
You paralyze me with disgust. You are spilling open like a gelatinous urchin belly. You paralyze me with disgust. You are spilling open like a gelatinous urchin belly.
I am aware of this. Please tell me how I can make myself appear more desirable to others. I would like to know my surgical options. I am aware of this. Please tell me how I can make myself appear more desirable to others. I would like to know my surgical options.
I hate you. I hate you.
I would like to end your life - but why? I know: meat. You are nothing but meat. You smell like diapers and sausage. I would like to end your life, but why? I know: meat. You are nothing but meat. You smell like diapers and sausage.
I disagree. Your waxy face looks ashen like a cadaverous larva, but I am enamoured with your smell, like a cranal flower with a frankincense opening, steeped in the essence of leather and mimosa. I disagree. Your waxy face looks ashen like a cadaverous larva, but I am enamoured with your smell, like a cranal flower with a frankincense opening, steeped in the essence of leather and mimosa.
You are a delight. If only I could remove your head altogether. You are a delight. If only I could remove your head altogether.
I will perform the surgery at once. I hope you are not too sensitive to pain. I will perform the surgery at once. I hope you are not too sensitive to pain.

View File

@@ -2,72 +2,95 @@
import os import os
import sys import sys
from typing import Tuple from typing import List, Tuple
import tweepy import tweepy
from time import sleep from time import sleep
from random import shuffle from random import shuffle
# Return our credentials from environment variables as UTF-8 bytes.
def get_arguments() -> Tuple[str, str, str, str]: def get_arguments() -> Tuple[bytes, bytes, bytes, bytes]:
consumer_key = os.environ['CONSUMER_KEY'] consumer_key: bytes = os.environ['CONSUMER_KEY'].encode('utf8')
consumer_secret = os.environ['CONSUMER_SECRET'] consumer_secret: bytes = os.environ['CONSUMER_SECRET'].encode('utf8')
access_token = os.environ['ACCESS_TOKEN'] access_token: bytes = os.environ['ACCESS_TOKEN'].encode('utf8')
access_token_secret = os.environ['ACCESS_TOKEN_SECRET'] access_token_secret: bytes = os.environ['ACCESS_TOKEN_SECRET'].encode('utf8')
return consumer_key, consumer_secret, access_token, access_token_secret return consumer_key, consumer_secret, access_token, access_token_secret
def populate_array(file_lines) -> list: # Copy the file lines to a new List[str] and shuffle it.
length = len(file_lines) def populate_array(file_lines: List[str]) -> List[str]:
array: List[str] = file_lines.copy()
array = []
for i in range(length):
array.append(i)
# Scramble like an egg.
shuffle(array) shuffle(array)
return array return array
# Main function.
def main() -> None: def main() -> None:
# Access and authorize our Twitter credentials consumer_key: bytes
consumer_secret: bytes
access_token: bytes
access_token_secret: bytes
# Access and set authentication method to our Twitter credentials.
consumer_key, consumer_secret, access_token, access_token_secret = get_arguments() consumer_key, consumer_secret, access_token, access_token_secret = get_arguments()
auth = tweepy.OAuth1UserHandler(consumer_key=consumer_key, consumer_secret=consumer_secret, auth: tweepy.OAuth1UserHandler = tweepy.OAuth1UserHandler(consumer_key=consumer_key, consumer_secret=consumer_secret,
access_token=access_token, access_token_secret=access_token_secret) access_token=access_token, access_token_secret=access_token_secret)
api = tweepy.API(auth=auth)
my_file = open('./everybody.txt', 'r', encoding='utf-8') # Creating an API object with our authentication method.
api: tweepy.API = tweepy.API(auth=auth)
array: List[str]
with open('./everybody.txt', 'r', encoding='utf-8') as my_file:
# Read lines one by one from my_file and assign to file_lines variable # Read lines one by one from my_file and assign to file_lines variable
file_lines = [x.strip() for x in my_file.readlines()] file_lines: List[str] = [x.strip() for x in my_file.readlines()]
# Close file. # Close file.
my_file.close() my_file.close()
# Create List[str] from file_lines.
array = populate_array(file_lines) array = populate_array(file_lines)
# Driving loop. # Driving loop.
while True: while True:
while array: while array:
tweet = file_lines[array.pop()] # Grab last element and then remove it.
tweet: str = array.pop()
try: try:
# Output the last element, which will be the tweet.
print(tweet) print(tweet)
# Create a tweet through the API.
api.update_status(tweet) api.update_status(tweet)
# Chill out for 1800 seconds.
sleep(1800) sleep(1800)
except tweepy.Forbidden as fe: except tweepy.Forbidden as fe:
print(f"{fe.api_errors}") # We probably tried to create a duplicate tweet, but say what happened.
print(fe.api_errors)
# Chill out for 30 seconds.
sleep(30) sleep(30)
except tweepy.BadRequest as be: except tweepy.BadRequest as be:
print(f"{be.api_errors}") # Something is wrong with our client, so say what happened.
print(be.api_errors)
# Bail. We shouldn't keep trying.
sys.exit(1) sys.exit(1)
except tweepy.TweepyException as te: except tweepy.TweepyException as te:
# Something very unexpected happened, so say what happened.
print(te) print(te)
# Bail. We shouldn't keep trying.
sys.exit(1) sys.exit(1)
# Let's do the time warp again.
array = populate_array(file_lines) array = populate_array(file_lines)
# Do not delete.
if __name__ == '__main__': if __name__ == '__main__':
main() main()