Telegram bot για εξατομικευμένη επιλογή άρθρων από το Habr

Για ερωτήσεις όπως "γιατί;" υπάρχει παλιότερο άρθρο - Natural Geektimes - κάνοντας καθαρότερο χώρο.

Υπάρχουν πολλά άρθρα, για υποκειμενικούς λόγους κάποια από αυτά δεν μου αρέσουν και κάποια, αντίθετα, είναι κρίμα να τα παραλείψω. Θα ήθελα να βελτιστοποιήσω αυτή τη διαδικασία και να εξοικονομήσω χρόνο.

Το παραπάνω άρθρο πρότεινε μια προσέγγιση σεναρίου εντός του προγράμματος περιήγησης, αλλά δεν μου άρεσε πολύ (παρόλο που το έχω χρησιμοποιήσει στο παρελθόν) για τους ακόλουθους λόγους:

  • Για διαφορετικά προγράμματα περιήγησης στον υπολογιστή/τηλέφωνό σας, πρέπει να το ρυθμίσετε ξανά, εάν είναι δυνατόν.
  • Το αυστηρό φιλτράρισμα από τους συγγραφείς δεν είναι πάντα βολικό.
  • Το πρόβλημα με τους συγγραφείς των οποίων τα άρθρα δεν θέλετε να χάσετε, ακόμα κι αν δημοσιεύονται μία φορά το χρόνο, δεν έχει λυθεί.

Το φιλτράρισμα που είναι ενσωματωμένο στον ιστότοπο με βάση τις αξιολογήσεις άρθρων δεν είναι πάντα βολικό, καθώς τα εξαιρετικά εξειδικευμένα άρθρα, παρά την αξία τους, μπορούν να λάβουν μια μάλλον μέτρια βαθμολογία.

Αρχικά, ήθελα να δημιουργήσω ένα RSS feed (ή ακόμα και πολλά), αφήνοντας εκεί μόνο ενδιαφέροντα πράγματα. Αλλά τελικά, αποδείχθηκε ότι η ανάγνωση του RSS δεν φαινόταν πολύ βολική: σε κάθε περίπτωση, για να σχολιάσετε/ψηφίσετε ένα άρθρο/να το προσθέσετε στα αγαπημένα σας, πρέπει να περάσετε από το πρόγραμμα περιήγησης. Γι' αυτό έγραψα ένα telegram bot που μου στέλνει ενδιαφέροντα άρθρα σε προσωπικό μήνυμα. Το ίδιο το Telegram κάνει όμορφες προεπισκοπήσεις από αυτές, οι οποίες, σε συνδυασμό με πληροφορίες σχετικά με τον συγγραφέα/αξιολόγηση/προβολές, φαίνονται αρκετά κατατοπιστικές.

Telegram bot για εξατομικευμένη επιλογή άρθρων από το Habr

Κάτω από την περικοπή υπάρχουν λεπτομέρειες όπως τα χαρακτηριστικά του έργου, η διαδικασία γραφής και οι τεχνικές λύσεις.

Εν συντομία για το bot

Αποθήκη: https://github.com/Kright/habrahabr_reader

Bot στο τηλεγράφημα: https://t.me/HabraFilterBot

Ο χρήστης ορίζει μια πρόσθετη βαθμολογία για ετικέτες και συγγραφείς. Μετά από αυτό, εφαρμόζεται ένα φίλτρο στα άρθρα - αθροίζονται η βαθμολογία του άρθρου στο Habré, η βαθμολογία χρήστη του συγγραφέα και ο μέσος όρος για τις αξιολογήσεις χρηστών ανά ετικέτα. Εάν το ποσό είναι μεγαλύτερο από ένα όριο που καθορίζεται από τον χρήστη, τότε το άρθρο περνά το φίλτρο.

Ένας παράπλευρος στόχος της συγγραφής ενός bot ήταν η απόκτηση διασκέδασης και εμπειρίας. Επιπλέον, το θύμιζα τακτικά στον εαυτό μου αυτό Δεν είμαι η Google, και επομένως πολλά πράγματα γίνονται όσο πιο απλά και μάλιστα πρωτόγονα γίνεται. Ωστόσο, αυτό δεν εμπόδισε τη διαδικασία συγγραφής του bot να διαρκέσει τρεις μήνες.

Έξω ήταν καλοκαίρι

Ο Ιούλιος τελείωνε και αποφάσισα να γράψω ένα bot. Και όχι μόνος, αλλά με έναν φίλο που ήταν mastering scala και ήθελε να γράψει κάτι σε αυτό. Η αρχή φαινόταν πολλά υποσχόμενη - ο κωδικός θα κόπηκε από μια ομάδα, το έργο φαινόταν εύκολο και σκέφτηκα ότι σε μερικές εβδομάδες ή ένα μήνα το bot θα ήταν έτοιμο.

Παρά το γεγονός ότι εγώ ο ίδιος γράφω κώδικα στο βράχο κατά καιρούς τα τελευταία χρόνια, κανείς συνήθως δεν βλέπει ή δεν κοιτάζει αυτόν τον κώδικα: έργα για κατοικίδια, δοκιμή κάποιων ιδεών, προεπεξεργασία δεδομένων, έλεγχος ορισμένων εννοιών από το FP. Με ενδιέφερε πραγματικά πώς μοιάζει η γραφή κώδικα σε μια ομάδα, γιατί ο κώδικας στο ροκ μπορεί να γραφτεί με πολύ διαφορετικούς τρόπους.

Τι θα μπορούσε να έχει πάει έτσι? Ωστόσο, ας μην βιαζόμαστε τα πράγματα.
Όλα όσα συμβαίνουν μπορούν να παρακολουθούνται χρησιμοποιώντας το ιστορικό δέσμευσης.

Ένας γνωστός δημιούργησε ένα αποθετήριο στις 27 Ιουλίου, αλλά δεν έκανε τίποτα άλλο, οπότε άρχισα να γράφω κώδικα.

30 Ιούλιο

Εν συντομία: Έγραψα μια ανάλυση της ροής rss του Habr.

  • com.github.pureconfig για την ανάγνωση των ρυθμίσεων typeafe απευθείας σε κατηγορίες case (αποδείχθηκε πολύ βολικό)
  • scala-xml για ανάγνωση xml: αφού αρχικά ήθελα να γράψω τη δική μου υλοποίηση για το rss feed και το rss feed είναι σε μορφή xml, χρησιμοποίησα αυτή τη βιβλιοθήκη για ανάλυση. Στην πραγματικότητα, εμφανίστηκε και η ανάλυση RSS.
  • scalatest για δοκιμές. Ακόμη και για μικροσκοπικά έργα, η σύνταξη δοκιμών εξοικονομεί χρόνο - για παράδειγμα, κατά την αποσφαλμάτωση της ανάλυσης xml, είναι πολύ πιο εύκολο να το κατεβάσετε σε ένα αρχείο, να γράψετε δοκιμές και να διορθώσετε σφάλματα. Όταν αργότερα εμφανίστηκε ένα σφάλμα με την ανάλυση κάποιου περίεργου html με μη έγκυρους χαρακτήρες utf-8, αποδείχθηκε ότι ήταν πιο βολικό να το τοποθετήσετε σε ένα αρχείο και να προσθέσετε μια δοκιμή.
  • ηθοποιοί από την Άκκα. Αντικειμενικά δεν χρειάζονταν καθόλου, αλλά το έργο γράφτηκε για πλάκα, ήθελα να τα δοκιμάσω. Ως αποτέλεσμα, είμαι έτοιμος να πω ότι μου άρεσε. Η ιδέα του OOP μπορεί να εξεταστεί από την άλλη πλευρά - υπάρχουν ηθοποιοί που ανταλλάσσουν μηνύματα. Το πιο ενδιαφέρον είναι ότι μπορείτε (και πρέπει) να γράψετε κώδικα με τέτοιο τρόπο ώστε το μήνυμα να μην φθάνει ή να μην υποβληθεί σε επεξεργασία (γενικά μιλώντας, όταν ο λογαριασμός εκτελείται σε έναν μόνο υπολογιστή, τα μηνύματα δεν πρέπει να χάνονται). Στην αρχή έξυνα το κεφάλι μου και υπήρχαν σκουπίδια στον κώδικα με τους ηθοποιούς να εγγράφονται ο ένας στον άλλον, αλλά στο τέλος κατάφερα να καταλήξω σε μια αρκετά απλή και κομψή αρχιτεκτονική. Ο κώδικας μέσα σε κάθε ηθοποιό μπορεί να θεωρηθεί ως single-threaded· όταν ένας ηθοποιός κολλάει, το acca τον επανεκκινεί - το αποτέλεσμα είναι ένα σύστημα αρκετά ανεκτικό σε σφάλματα.

9 Αύγουστο

Πρόσθεσα στο έργο scala-scrapper για ανάλυση σελίδων html από το Habr (για εξαγωγή πληροφοριών όπως βαθμολογία άρθρου, αριθμός σελιδοδεικτών κ.λπ.).

Και γάτες. Αυτά στο βράχο.

Telegram bot για εξατομικευμένη επιλογή άρθρων από το Habr

Στη συνέχεια διάβασα ένα βιβλίο σχετικά με τις κατανεμημένες βάσεις δεδομένων, μου άρεσε η ιδέα του CRDT (Conflict-free replicated data type), https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type, habr), έτσι δημοσίευσα μια κατηγορία τύπων μιας εναλλακτικής ημιομάδας για πληροφορίες σχετικά με το άρθρο στο Habré.

Στην πραγματικότητα, η ιδέα είναι πολύ απλή - έχουμε μετρητές που αλλάζουν μονότονα. Ο αριθμός των προσφορών αυξάνεται σταδιακά, όπως και ο αριθμός των συν (καθώς και ο αριθμός των πλην). Εάν έχω δύο εκδόσεις πληροφοριών σχετικά με ένα άρθρο, τότε μπορώ να τις "συγχώνω σε μία" - η κατάσταση του μετρητή που είναι μεγαλύτερος θεωρείται πιο σχετική.

Ημιομάδα σημαίνει ότι δύο αντικείμενα με πληροφορίες για ένα άρθρο μπορούν να συγχωνευθούν σε ένα. Αντικατάσταση σημαίνει ότι μπορείτε να συγχωνεύσετε και τα δύο A + B και B + A, το αποτέλεσμα δεν εξαρτάται από τη σειρά και στο τέλος θα παραμείνει η νεότερη έκδοση. Παρεμπιπτόντως, εδώ υπάρχει και συνειρμικότητα.

Για παράδειγμα, όπως είχε προγραμματιστεί, το rss μετά την ανάλυση παρείχε ελαφρώς εξασθενημένες πληροφορίες σχετικά με το άρθρο - χωρίς μετρήσεις όπως ο αριθμός των προβολών. Στη συνέχεια, ένας ειδικός ηθοποιός πήρε πληροφορίες για τα άρθρα και έτρεξε στις σελίδες html για να το ενημερώσει και να το συγχωνεύσει με την παλιά έκδοση.

Γενικά, όπως και στο akka, δεν χρειαζόταν κάτι τέτοιο, μπορούσατε απλώς να αποθηκεύσετε το updateDate για το άρθρο και να πάρετε ένα νεότερο χωρίς συγχωνεύσεις, αλλά ο δρόμος της περιπέτειας με οδήγησε.

12 Αύγουστο

Άρχισα να νιώθω πιο ελεύθερος και, για πλάκα, έκανα κάθε συνομιλία ξεχωριστό ηθοποιό. Θεωρητικά, ένας ηθοποιός από μόνος του ζυγίζει περίπου 300 byte και μπορούν να δημιουργηθούν σε εκατομμύρια, επομένως αυτή είναι μια απολύτως φυσιολογική προσέγγιση. Μου φαίνεται ότι η λύση αποδείχθηκε αρκετά ενδιαφέρουσα:

Ένας ηθοποιός ήταν μια γέφυρα μεταξύ του διακομιστή τηλεγραφήματος και του συστήματος μηνυμάτων στην Άκκα. Απλώς λάμβανε μηνύματα και τα έστελνε στον επιθυμητό ηθοποιό συνομιλίας. Ο ηθοποιός συνομιλίας θα μπορούσε να στείλει κάτι πίσω ως απάντηση - και θα έστελνε πίσω στο τηλεγράφημα. Αυτό που ήταν πολύ βολικό είναι ότι αυτός ο ηθοποιός αποδείχτηκε όσο το δυνατόν πιο απλός και περιείχε μόνο τη λογική για να απαντήσει στα μηνύματα. Παρεμπιπτόντως, πληροφορίες σχετικά με νέα άρθρα ήρθαν σε κάθε συνομιλία, αλλά και πάλι δεν βλέπω κανένα πρόβλημα σε αυτό.

Γενικά, το ρομπότ λειτουργούσε ήδη, απαντούσε σε μηνύματα, αποθήκευε μια λίστα άρθρων που αποστέλλονταν στον χρήστη και ήδη σκεφτόμουν ότι το bot ήταν σχεδόν έτοιμο. Πρόσθεσα σιγά σιγά μικρές δυνατότητες, όπως η κανονικοποίηση ονομάτων και ετικετών συγγραφέων (αντικαθιστώντας το "sd f" με το "s_d_f").

Έμεινε μόνο ένα πράγμα μικρό αλλά — το κράτος δεν σώθηκε πουθενά.

Ολα πήγαν στραβά

Ίσως έχετε παρατηρήσει ότι έγραψα το bot κυρίως μόνος μου. Έτσι, ο δεύτερος συμμετέχων συμμετείχε στην ανάπτυξη και οι ακόλουθες αλλαγές εμφανίστηκαν στον κώδικα:

  • Το MongoDB φάνηκε να αποθηκεύει την κατάσταση. Ταυτόχρονα, τα αρχεία καταγραφής στο έργο έσπασαν, επειδή για κάποιο λόγο η Monga άρχισε να τα στέλνει με ανεπιθύμητα μηνύματα και κάποιοι απλά τα απενεργοποίησαν παγκοσμίως.
  • Ο ηθοποιός της γέφυρας στο Telegram μεταμορφώθηκε πέρα ​​από την αναγνώριση και άρχισε να αναλύει τα μηνύματα ο ίδιος.
  • Οι ηθοποιοί για συνομιλίες αποκόπηκαν ανελέητα και αντικαταστάθηκαν από έναν ηθοποιό που έκρυβε όλες τις πληροφορίες για όλες τις συνομιλίες ταυτόχρονα. Για κάθε φτάρνισμα, αυτός ο ηθοποιός έμπαινε σε μπελάδες. Λοιπόν, ναι, όπως όταν ενημερώνετε πληροφορίες για ένα άρθρο, η αποστολή τους σε όλους τους συντελεστές συνομιλίας είναι δύσκολη (είμαστε σαν την Google, εκατομμύρια χρήστες περιμένουν ένα εκατομμύριο άρθρα στη συνομιλία για τον καθένα), αλλά κάθε φορά που ενημερώνεται η συνομιλία, είναι φυσιολογικό να πας στη Μόνγκα. Όπως κατάλαβα πολύ αργότερα, η λειτουργική λογική των συνομιλιών επίσης κόπηκε τελείως και στη θέση της εμφανίστηκε κάτι που δεν λειτουργούσε.
  • Δεν υπάρχει ίχνος από τις κατηγορίες τύπων.
  • Κάποια ανθυγιεινή λογική έχει εμφανιστεί στους ηθοποιούς με τις συνδρομές τους μεταξύ τους, οδηγώντας σε κατάσταση αγώνα.
  • Δομές δεδομένων με πεδία τύπου Option[Int] μετατράπηκε σε Int με μαγικές προεπιλεγμένες τιμές όπως -1. Αργότερα συνειδητοποίησα ότι το mongoDB αποθηκεύει το json και δεν υπάρχει τίποτα κακό να το αποθηκεύεις εκεί Option Λοιπόν, ή τουλάχιστον αναλύστε το -1 ως Κανένα, αλλά εκείνη τη στιγμή δεν το ήξερα αυτό και πίστευα ότι «έτσι έπρεπε να είναι». Δεν έγραψα αυτόν τον κωδικό και δεν μπήκα στον κόπο να τον αλλάξω προς το παρόν.
  • Ανακάλυψα ότι η δημόσια διεύθυνση IP μου τείνει να αλλάζει και κάθε φορά έπρεπε να την προσθέτω στη λίστα επιτρεπόμενων του Mongo. Ξεκίνησα το bot τοπικά, η Monga ήταν κάπου στους διακομιστές της Monga ως εταιρεία.
  • Ξαφνικά, η κανονικοποίηση των ετικετών και η μορφοποίηση μηνυμάτων για τηλεγραφήματα εξαφανίστηκε. (Χμμ, γιατί να είναι αυτό;)
  • Μου άρεσε που η κατάσταση του bot αποθηκεύεται σε μια εξωτερική βάση δεδομένων και όταν επανεκκινείται συνεχίζει να λειτουργεί σαν να μην είχε συμβεί τίποτα. Ωστόσο, αυτό ήταν το μόνο συν.

Το δεύτερο άτομο δεν βιαζόταν ιδιαίτερα και όλες αυτές οι αλλαγές εμφανίστηκαν σε ένα μεγάλο σωρό ήδη στις αρχές Σεπτεμβρίου. Δεν εκτίμησα αμέσως την κλίμακα της καταστροφής που προέκυψε και άρχισα να καταλαβαίνω τη δουλειά της βάσης δεδομένων, γιατί... Δεν έχω ασχοληθεί ποτέ ξανά μαζί τους. Μόνο αργότερα κατάλαβα πόσος κώδικας εργασίας κόπηκε και πόσα σφάλματα προστέθηκαν στη θέση του.

Σεπτέμβριος

Στην αρχή σκέφτηκα ότι θα ήταν χρήσιμο να κυριαρχήσω στο Monga και να το κάνω καλά. Μετά άρχισα σιγά σιγά να καταλαβαίνω ότι η οργάνωση της επικοινωνίας με τη βάση δεδομένων είναι επίσης μια τέχνη στην οποία μπορείς να κάνεις πολλούς αγώνες και απλά να κάνεις λάθη. Για παράδειγμα, εάν ο χρήστης λάβει δύο μηνύματα όπως /subscribe - και ως απάντηση σε κάθε ένα θα δημιουργήσουμε μια καταχώρηση στον πίνακα, επειδή κατά τη στιγμή της επεξεργασίας αυτών των μηνυμάτων ο χρήστης δεν είναι εγγεγραμμένος. Έχω την υποψία ότι η επικοινωνία με τη Monga στη σημερινή της μορφή δεν είναι γραμμένη με τον καλύτερο τρόπο. Για παράδειγμα, οι ρυθμίσεις του χρήστη δημιουργήθηκαν τη στιγμή που εγγράφηκε. Αν προσπαθούσε να τα αλλάξει πριν το γεγονός της συνδρομής... το bot δεν απάντησε τίποτα, γιατί ο κωδικός του ηθοποιού μπήκε στη βάση δεδομένων για τις ρυθμίσεις, δεν τον βρήκε και χάλασε. Όταν ρωτήθηκε γιατί να μην δημιουργήσω ρυθμίσεις όπως χρειάζεται, έμαθα ότι δεν χρειάζεται να τις αλλάξω εάν ο χρήστης δεν έχει εγγραφεί... Το σύστημα φιλτραρίσματος μηνυμάτων έγινε κατά κάποιο τρόπο μη προφανώς, και ακόμη και μετά από μια προσεκτική ματιά στον κώδικα μπορούσα δεν καταλαβαίνω αν προοριζόταν αρχικά με αυτόν τον τρόπο ή υπάρχει κάποιο σφάλμα εκεί.

Δεν υπήρχε λίστα άρθρων που υποβλήθηκαν στη συνομιλία· αντ' αυτού, μου προτάθηκε να τα γράψω εγώ. Αυτό με εξέπληξε - γενικά, δεν ήμουν αντίθετος στο να σέρνονται όλα τα πράγματα στο έργο, αλλά θα ήταν λογικό για αυτόν που έφερε αυτά τα πράγματα και τα έσφιξε. Αλλά όχι, ο δεύτερος συμμετέχων φαινόταν να εγκαταλείπει τα πάντα, αλλά είπε ότι η λίστα μέσα στη συνομιλία ήταν υποτιθέμενη κακή λύση και ότι ήταν απαραίτητο να δημιουργήσετε ένα σημάδι με συμβάντα όπως "ένα άρθρο y στάλθηκε στον χρήστη x". Στη συνέχεια, εάν ο χρήστης ζητούσε να στείλει νέα άρθρα, ήταν απαραίτητο να σταλεί ένα αίτημα στη βάση δεδομένων, το οποίο θα επέλεγε συμβάντα που σχετίζονται με τον χρήστη από τα συμβάντα, θα λάμβανε επίσης μια λίστα νέων άρθρων, θα τα φιλτράρει, θα τα στέλνει στον χρήστη και πετάξτε τα γεγονότα σχετικά με αυτό πίσω στη βάση δεδομένων.

Ο δεύτερος συμμετέχων παρασύρθηκε κάπου προς τις αφαιρέσεις, όταν το bot θα λάβει όχι μόνο άρθρα από το Habr και θα σταλεί όχι μόνο στο τηλεγράφημα.

Κατά κάποιο τρόπο υλοποίησα εκδηλώσεις με τη μορφή ξεχωριστού σήματος για το δεύτερο δεκαπενθήμερο του Σεπτεμβρίου. Δεν είναι βέλτιστο, αλλά τουλάχιστον το bot άρχισε να λειτουργεί και άρχισε να μου στέλνει άρθρα ξανά και σιγά σιγά κατάλαβα τι συνέβαινε στον κώδικα.

Τώρα μπορείτε να επιστρέψετε στην αρχή και να θυμάστε ότι το αποθετήριο δεν δημιουργήθηκε αρχικά από εμένα. Τι θα μπορούσε να έχει γίνει έτσι; Το αίτημα έλξης μου απορρίφθηκε. Αποδείχτηκε ότι είχα κώδικα redneck, ότι δεν ήξερα πώς να δουλεύω σε μια ομάδα και έπρεπε να διορθώσω σφάλματα στην τρέχουσα καμπύλη υλοποίησης και όχι να τον βελτιώσω σε κατάσταση χρήσης.

Αναστατώθηκα και κοίταξα το ιστορικό δεσμεύσεων και την ποσότητα του κώδικα που γράφτηκε. Κοίταξα στιγμές που είχαν αρχικά γραφτεί καλά, και μετά έσπασαν...

F*rk it

Θυμήθηκα το άρθρο Δεν είστε η Google.

Σκέφτηκα ότι κανείς δεν χρειάζεται πραγματικά μια ιδέα χωρίς υλοποίηση. Σκέφτηκα ότι θέλω να έχω ένα λειτουργικό bot, το οποίο θα λειτουργεί σε ένα μόνο αντίγραφο σε έναν μόνο υπολογιστή ως ένα απλό πρόγραμμα java. Ξέρω ότι το bot μου θα λειτουργεί για μήνες χωρίς επανεκκινήσεις, μιας και έχω ήδη γράψει τέτοια bot στο παρελθόν. Αν πέσει ξαφνικά και δεν στείλει στον χρήστη άλλο άρθρο, ο ουρανός δεν θα πέσει στο έδαφος και δεν θα συμβεί τίποτα καταστροφικό.

Γιατί χρειάζομαι το Docker, το mongoDB και άλλο «σοβαρό» λογισμικό φορτίου, εάν ο κώδικας απλά δεν λειτουργεί ή λειτουργεί στραβά;

Πήρα το έργο και έκανα τα πάντα όπως ήθελα.

Telegram bot για εξατομικευμένη επιλογή άρθρων από το Habr

Περίπου την ίδια περίοδο, άλλαξα δουλειά και ο ελεύθερος χρόνος μου έλειπε πολύ. Το πρωί ξύπνησα ακριβώς στο τρένο, το βράδυ επέστρεψα αργά και δεν ήθελα πια να κάνω τίποτα. Δεν έκανα τίποτα για λίγο, μετά η επιθυμία να τελειώσω το bot με κυρίευσε και άρχισα να ξαναγράφω σιγά σιγά τον κώδικα ενώ πήγαινα με το αυτοκίνητο στη δουλειά το πρωί. Δεν θα πω ότι ήταν παραγωγικό: το να κάθεσαι σε ένα τρένο που κουνούσε με ένα φορητό υπολογιστή στην αγκαλιά σου και να κοιτάς την υπερχείλιση στοίβας από το τηλέφωνό σου δεν είναι πολύ βολικό. Ωστόσο, ο χρόνος που δαπανήθηκε για τη σύνταξη κώδικα πέρασε εντελώς απαρατήρητος και το έργο άρχισε σιγά-σιγά να κινείται προς μια κατάσταση λειτουργίας.

Κάπου στο πίσω μέρος του μυαλού μου υπήρχε ένα σκουλήκι αμφιβολίας που ήθελε να χρησιμοποιήσει το mongoDB, αλλά σκέφτηκα ότι εκτός από τα πλεονεκτήματα της "αξιόπιστης" αποθήκευσης κατάστασης, υπήρχαν και αξιοσημείωτα μειονεκτήματα:

  • Η βάση δεδομένων γίνεται άλλο ένα σημείο αποτυχίας.
  • Ο κώδικας γίνεται πιο περίπλοκος και θα μου πάρει περισσότερο χρόνο για να τον γράψω.
  • Ο κώδικας γίνεται αργός και αναποτελεσματικός· αντί να αλλάξουν ένα αντικείμενο στη μνήμη, οι αλλαγές αποστέλλονται στη βάση δεδομένων και, εάν χρειάζεται, ανασύρονται.
  • Υπάρχουν περιορισμοί στον τύπο αποθήκευσης συμβάντων σε ξεχωριστό πίνακα, οι οποίοι σχετίζονται με τις ιδιαιτερότητες της βάσης δεδομένων.
  • Η δοκιμαστική έκδοση του Monga έχει κάποιους περιορισμούς και, αν τους συναντήσετε, θα πρέπει να εκκινήσετε και να ρυθμίσετε το Monga σε κάτι.

Έκοψα το monga, τώρα η κατάσταση του bot αποθηκεύεται απλώς στη μνήμη του προγράμματος και από καιρό σε καιρό αποθηκεύεται σε ένα αρχείο με τη μορφή json. Ίσως στα σχόλια να γράψουν ότι κάνω λάθος, ότι εδώ πρέπει να χρησιμοποιείται η βάση δεδομένων κ.λπ. Αλλά αυτό είναι το έργο μου, η προσέγγιση με το αρχείο είναι όσο το δυνατόν πιο απλή και λειτουργεί με διαφανή τρόπο.

Έριξε μαγικές τιμές όπως -1 και επέστρεψε τις κανονικές Option, πρόσθεσε την αποθήκευση ενός πίνακα κατακερματισμού με αποσταλμένα άρθρα πίσω στο αντικείμενο με πληροφορίες συνομιλίας. Προστέθηκε διαγραφή πληροφοριών για άρθρα παλαιότερα των πέντε ημερών, ώστε να μην αποθηκεύονται τα πάντα. Έφερα την καταγραφή σε κατάσταση λειτουργίας - τα αρχεία καταγραφής γράφονται σε λογικές ποσότητες τόσο στο αρχείο όσο και στην κονσόλα. Προστέθηκαν πολλές εντολές διαχειριστή, όπως αποθήκευση κατάστασης ή λήψη στατιστικών στοιχείων, όπως ο αριθμός των χρηστών και των άρθρων.

Διορθώθηκαν πολλά μικρά πράγματα: για παράδειγμα, για τα άρθρα υποδεικνύεται πλέον ο αριθμός των προβολών, των "μου αρέσει", "δεν μου αρέσει" και των σχολίων τη στιγμή της μετάβασης του φίλτρου του χρήστη. Γενικά, είναι εκπληκτικό πόσα μικρά πράγματα έπρεπε να διορθωθούν. Κράτησα μια λίστα, σημείωσα όλες τις «παρατυπίες» εκεί και τις διόρθωσα όσο το δυνατόν περισσότερο.

Για παράδειγμα, πρόσθεσα τη δυνατότητα να ορίσω όλες τις ρυθμίσεις απευθείας σε ένα μήνυμα:

/subscribe
/rating +20
/author a -30
/author s -20
/author p +9000
/tag scala 20
/tag akka 50

Και άλλη ομάδα /settings τα εμφανίζει ακριβώς σε αυτή τη μορφή, μπορείτε να πάρετε το κείμενο από αυτό και να στείλετε όλες τις ρυθμίσεις σε έναν φίλο.
Φαίνεται σαν μικρό πράγμα, αλλά υπάρχουν δεκάδες παρόμοιες αποχρώσεις.

Εφαρμοσμένο φιλτράρισμα άρθρων με τη μορφή απλού γραμμικού μοντέλου - ο χρήστης μπορεί να ορίσει μια πρόσθετη βαθμολογία για τους συγγραφείς και τις ετικέτες, καθώς και μια τιμή κατωφλίου. Εάν το άθροισμα της βαθμολογίας του συγγραφέα, της μέσης βαθμολογίας για ετικέτες και της πραγματικής βαθμολογίας του άρθρου είναι μεγαλύτερη από την τιμή κατωφλίου, τότε το άρθρο εμφανίζεται στον χρήστη. Μπορείτε είτε να ζητήσετε από το bot άρθρα με την εντολή /new, είτε να εγγραφείτε στο bot και θα στέλνει άρθρα σε προσωπικό μήνυμα οποιαδήποτε στιγμή της ημέρας.

Σε γενικές γραμμές, είχα μια ιδέα για κάθε άρθρο να αντλεί περισσότερες δυνατότητες (κόμβοι, αριθμός σχολίων, σελιδοδείκτες, δυναμική αλλαγών βαθμολογίας, ποσότητα κειμένου, εικόνες και κώδικας στο άρθρο, λέξεις-κλειδιά) και να δείχνει στον χρήστη ένα ok/ Όχι εντάξει ψηφίστε κάτω από κάθε άρθρο και εκπαιδεύστε ένα μοντέλο για κάθε χρήστη, αλλά ήμουν πολύ τεμπέλης.

Επιπλέον, η λογική του έργου δεν θα είναι τόσο εμφανής. Τώρα μπορώ να ορίσω χειροκίνητα μια βαθμολογία +9000 για τον ασθενήΜηδέν και με βαθμολογία κατωφλίου +20 θα είμαι εγγυημένος ότι θα λάβω όλα τα άρθρα του (εκτός, φυσικά, αν ορίσω -100500 για ορισμένες ετικέτες).

Η τελική αρχιτεκτονική αποδείχθηκε αρκετά απλή:

  1. Ένας ηθοποιός που αποθηκεύει την κατάσταση όλων των συνομιλιών και των άρθρων. Φορτώνει την κατάστασή του από ένα αρχείο στο δίσκο και το αποθηκεύει πίσω από καιρό σε καιρό, κάθε φορά σε ένα νέο αρχείο.
  2. Ένας ηθοποιός που επισκέπτεται τη ροή RSS από καιρό σε καιρό, μαθαίνει για νέα άρθρα, κοιτάζει τους συνδέσμους, αναλύει και στέλνει αυτά τα άρθρα στον πρώτο ηθοποιό. Επιπλέον, μερικές φορές ζητά μια λίστα άρθρων από τον πρώτο ηθοποιό, επιλέγει αυτά που δεν είναι παλαιότερα των τριών ημερών, αλλά δεν έχουν ενημερωθεί για μεγάλο χρονικό διάστημα και τα ενημερώνει.
  3. Ένας ηθοποιός που επικοινωνεί με ένα τηλεγράφημα. Έφερα ακόμα το μήνυμα αναλύοντας εντελώς εδώ. Με φιλικό τρόπο, θα ήθελα να το χωρίσω σε δύο - έτσι ώστε το ένα να αναλύει τα εισερχόμενα μηνύματα και το δεύτερο να ασχολείται με προβλήματα μεταφοράς, όπως η εκ νέου αποστολή μη απεσταλμένων μηνυμάτων. Τώρα δεν υπάρχει εκ νέου αποστολή και ένα μήνυμα που δεν έφτασε λόγω σφάλματος απλώς θα χαθεί (εκτός αν σημειωθεί στα αρχεία καταγραφής), αλλά μέχρι στιγμής αυτό δεν έχει δημιουργήσει κανένα πρόβλημα. Ίσως προκύψουν προβλήματα εάν ένα σωρό άτομα εγγραφούν στο bot και φτάσω το όριο για την αποστολή μηνυμάτων).

Αυτό που μου άρεσε είναι ότι χάρη στο akka, οι πτώσεις των ηθοποιών 2 και 3 γενικά δεν επηρεάζουν την απόδοση του bot. Ίσως κάποια άρθρα να μην ενημερωθούν εγκαίρως ή κάποια μηνύματα να μην φτάνουν στο τηλεγράφημα, αλλά ο λογαριασμός κάνει επανεκκίνηση του ηθοποιού και όλα συνεχίζουν να λειτουργούν. Αποθηκεύω τις πληροφορίες ότι το άρθρο εμφανίζεται στον χρήστη μόνο όταν ο ηθοποιός του τηλεγραφήματος απαντήσει ότι έχει παραδώσει με επιτυχία το μήνυμα. Το χειρότερο πράγμα που με απειλεί είναι να στείλω το μήνυμα πολλές φορές (αν παραδοθεί, αλλά η επιβεβαίωση χάνεται κατά κάποιο τρόπο). Κατ' αρχήν, αν ο πρώτος ηθοποιός δεν αποθήκευε το κράτος μέσα του, αλλά επικοινωνούσε με κάποια βάση δεδομένων, τότε θα μπορούσε επίσης να πέσει ανεπαίσθητα και να επιστρέψει στη ζωή. Θα μπορούσα να δοκιμάσω και το akka persistence για να επαναφέρω την κατάσταση των ηθοποιών, αλλά η τρέχουσα εφαρμογή μου ταιριάζει με την απλότητά της. Δεν είναι ότι ο κώδικας μου κολλούσε συχνά - αντίθετα, κατέβαλα μεγάλη προσπάθεια για να το κάνω αδύνατο. Αλλά συμβαίνει και η ικανότητα να σπάσω το πρόγραμμα σε μεμονωμένα κομμάτια-ηθοποιούς μου φάνηκε πολύ βολικό και πρακτικό.

Πρόσθεσα το circle-ci ώστε αν σπάσει ο κωδικός να το μάθετε αμέσως. Τουλάχιστον, σημαίνει ότι ο κώδικας έχει σταματήσει να μεταγλωττίζεται. Αρχικά ήθελα να προσθέσω travis, αλλά έδειχνε μόνο τα έργα μου χωρίς πιρούνια. Γενικά, και τα δύο αυτά πράγματα μπορούν να χρησιμοποιηθούν ελεύθερα σε ανοιχτά αποθετήρια.

Αποτελέσματα της

Είναι ήδη Νοέμβριος. Το bot είναι γραμμένο, το χρησιμοποιώ τις τελευταίες δύο εβδομάδες και μου άρεσε. Αν έχετε ιδέες για βελτίωση, γράψτε. Δεν βλέπω το νόημα στη δημιουργία εσόδων - αφήστε το να λειτουργήσει και στείλτε ενδιαφέροντα άρθρα.

Σύνδεσμος bot: https://t.me/HabraFilterBot
Github: https://github.com/Kright/habrahabr_reader

Μικρά συμπεράσματα:

  • Ακόμη και ένα μικρό έργο μπορεί να πάρει πολύ χρόνο.
  • Δεν είστε η Google. Δεν έχει νόημα να πυροβολείς σπουργίτια από κανόνι. Μια απλή λύση μπορεί να λειτουργήσει εξίσου καλά.
  • Τα έργα για κατοικίδια είναι πολύ καλά για πειραματισμούς με νέες τεχνολογίες.
  • Τα bots του Telegram γράφονται πολύ απλά. Αν δεν ήταν η «ομαδική εργασία» και τα πειράματα με την τεχνολογία, το bot θα είχε γραφτεί σε μια ή δύο εβδομάδες.
  • Το μοντέλο ηθοποιού είναι ένα ενδιαφέρον πράγμα που ταιριάζει καλά με κώδικα πολλαπλών νημάτων και ανοχής σε σφάλματα.
  • Νομίζω ότι πήρα μια γεύση του γιατί η κοινότητα ανοιχτού κώδικα αγαπά τα πιρούνια.
  • Οι βάσεις δεδομένων είναι καλές επειδή η κατάσταση της εφαρμογής δεν εξαρτάται πλέον από σφάλματα/επανεκκινήσεις της εφαρμογής, αλλά η εργασία με μια βάση δεδομένων περιπλέκει τον κώδικα και επιβάλλει περιορισμούς στη δομή δεδομένων.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο